Question

Je suis en train d'écrire une application simple qui permet de télécharger des images d'un utilisateur. Après le téléchargement, l'utilisateur peut les marquer ou les supprimer.

Je me suis dit comment télécharger les fichiers et les enregistrer une fois que les fichiers sont téléchargés. Je garde le suivi d'un chemin global où les images sont conservées. Dans la base de données que je garde les méta-données sur les images comme nom de fichier, balises, etc.

J'utilise Java / JSP (en particulier du cadre Stripes, mais mon problème est générique).

Ma question est de savoir où je garde ces fichiers d'images une fois qu'ils sont téléchargés?

En ce moment j'ai deux applications Web déployées sur un serveur Tomcat. L'une des principales applications web et l'autre est le où je télécharge les images.

Mais cela ne fonctionne pas comme je ne peux pas voir les images téléchargées dans l'application principale jusqu'à ce que je redéployer / redémarrer Tomcat.

Il semble que Tomcat ne capte pas les nouvelles images téléchargées automatiquement.

Quelqu'un at-il des solutions?

Ceci est un projet simple, donc je ne veux pas les stocker dans une base de données ou utiliser Apache pour les images. C'est tout simplement trop compliqué pour ce petit projet.

Merci.

Était-ce utile?

La solution

Je ne vous conseille pas stocker les images dans la base de données, mais vous voulez stocker le chemin d'image dans la base de données. Cela vous permettra de stocker l'image à peu près partout.

Puisque vous utilisez deux applications tomcat, votre meilleur pari peut être pour stocker les images de l'extérieur, soit l'application et diffusez l'image à l'utilisateur au lieu de laisser tomcat gérer les fichiers. Dans le cas contraire, je vous demander pourquoi vous essayez de le faire avec deux applications Web.

Autres conseils

Cependant, le stockage des images téléchargées dans le répertoire web-app est pas une chose à faire, et vous le savez.

Par ailleurs, vous pouvez regarder cette stackoverflow enfilez , discuté ces derniers temps où stocker les images. Il pourrait ne pas résoudre votre problème, sûrement vous donnera plus de confiance sur ce que vous faites.

Je l'ai résolu ce problème de différentes manières.

Tout d'abord, la manière non-portable, est que Glassfish (et je ne crois Tomcat aussi) vous permet de mapper un répertoire externe dans la hiérarchie webapps. Cela fonctionne vraiment bien et fait exactement ce que vous voulez. Il vous permet de stocker vos images dans un répertoire externe loin de votre webapp, mais les servir encore vers le haut.

Cependant, cette technique est portable.

La façon de je l'ai fait est portably en créant un filtre.

Vous placez le filtre quelque part évidente, dire "/ images".

Qu'est-ce que le filtre n'est ceci:

  • il vérifie l'image (ou quoi que ce soit, il fonctionne avec une ressource statique) dans un répertoire spécial au sein de la webapp. Pour notre exemple, nous allons utiliser l'URL "/ webapp / images".

  • si le fichier n'existe pas, on copie le fichier de votre emplacement externe à l'endroit approprié dans la webapp. Alors, disons que l'url reqyest est « /images/banner.gif ». Et que vos fichiers sont stockés sur le disque à « / home / app / images ». Ainsi, notre fichier source est « /home/app/images/banner.gif ». Nous copions ensuite à l'endroit où nous voulons dans l'arbre webapp. Nous utilisons « ServletContext.getRealPath » pour cela. Ainsi, la destination sera "ServletContext.get Realpath (" / webapp / images / banner.gif "). Il suffit de copier la source à la destination.

  • si le fichier existait déjà, ou existe maintenant, il suffit d'envoyer à l'image réelle à /webapp/images/banner.gif.

En effet, vous finissez par avoir un cache de fichiers au sein de votre arbre de déploiement webapps. L'inconvénient est que c'est un cache, il doit être maintenu (à savoir que vous devriez vérifier si l'original est plus récent que votre cache, assurez-vous de supprimer si la source est supprimée, etc.). , Il fait double emploi également vos ressources, vos images consommeront, par la suite, deux fois plus d'espace disque. Enfin, il y a le coût de la copie initiale au démarrage.

Cependant, il fonctionne, et il vous évite d'avoir à servir des ressources statiques en utilisant votre propre code. (Quelle est la 3ème solution, carte un filtre / servlet pour intercepter les URL et diffusez simplement votre auto.)

Je regardais la construction au sein de Tomcat (en supposant qu'il existe) pour faire le mapping pour vous. Je sais qu'il existe dans Glassfish. (Google alternatedocroot pour Glassfish pour voir comment cela fonctionne.)

J'utilisais deux applications web pour éviter une écriture des images téléchargées dans le cas où je redéployer un nouveau fichier de guerre d'application principale.

Mais comme vous le mentionnez, il n'y a pas d'autre choix que de les diffuser à travers un Servlet ou quelque chose que je suppose que je peux les garder en dehors tomcat.

Je voulais éviter d'écrire ce streaming Servlet. Trop petit projet pour faire face à tout le désordre (comme le type de contenu approprié, 404, etc.) tout en écrivant le servlet streaming.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Image streaming Servlet.
 */
public class ImageDisplayServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImageDisplayServlet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String relativePath = trimToEmpty(request.getPathInfo());

        // Make sure no one try to screw with us. 
        // This is important as user can literally access any file if we are not careful
        if(isXSSAttack(relativePath) == false) {
            String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
            File file = new File(pathToFile);

            System.out.println("Looking for file " + file.getAbsolutePath());

            // show a 404 page
            if(!file.exists() || !file.isFile()) {
                httpError(404, response);
            } else {
                try {
                    streamImageFile(file, response);
                } catch(Exception e) {
                    // Tell the user there was some internal server error.\
                    // 500 - Internal server error.
                    httpError(500, response);
                    e.printStackTrace();
                }
            }
        } else {
            // what to do if i think it is a XSS attack ?!?
        }
    }

    private void streamImageFile(File file, HttpServletResponse response) {
        // find the right MIME type and set it as content type
        response.setContentType(getContentType(file));
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            response.setContentLength((int) file.length());

            // Use Buffered Stream for reading/writing.
            bis = new BufferedInputStream(new FileInputStream(file));
            bos = new BufferedOutputStream(response.getOutputStream());

            byte[] buff = new byte[(int) file.length()];
            int bytesRead;

            // Simple read/write loop.
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (Exception e) {

            throw new RuntimeException(e);
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
        } 
    }

    private String getContentType(File file) {
        if(file.getName().length() > 0) {
            String[] parts = file.getName().split("\\.");
            if(parts.length > 0) {
                // only last part interests me
                String extention = parts[parts.length - 1];
                if(extention.equalsIgnoreCase("jpg")) {
                    return "image/jpg";
                } else if(extention.equalsIgnoreCase("gif")) {
                    return "image/gif"; 
                } else if(extention.equalsIgnoreCase("png")) {
                    return "image/png";
                }
            }
        }
        throw new RuntimeException("Can not find content type for the file " +  file.getAbsolutePath());
    }

    private String trimToEmpty(String pathInfo) {
        if(pathInfo == null) {
            return "";
        } else {
            return pathInfo.trim();
        }
    }

    private void httpError(int statusCode, HttpServletResponse response) {
        try {
            response.setStatus(statusCode);
            response.setContentType("text/html");
            PrintWriter writer = response.getWriter();
            writer.append("<html><body><h1>Error Code: " + statusCode + "</h1><body></html>");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isXSSAttack(String path) {
        boolean xss = false;
        // Split on the bases of know file separator
        String[] parts = path.split("/|\\\\");

        // Now verify that no part contains anything harmful
        for(String part : parts) {
            // No double dots .. 
            // No colons :
            // No semicolons ;
            if(part.trim().contains("..") || part.trim().contains(":") || part.trim().contains(";")) {
                // Fire in the hole!
                xss = true;
                break;
            }
        }
        return xss;
    }

    /**
     * @see HttpServlet#doPost(Ht/promotions/some.jpgtpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

Ok Voici un Servlet que je me suis vite écrit qui peut diffuser des images:

Voici la liste des limites et connaître les problèmes:

  • Peut être utilisé de la vulnérabilité XSS avec soin
  • Pas de prêt pour la production utilisation comme référence
  • Images doivent dans le répertoire d'applications Web. Peut être facilement changer mais je trop paresseux (il ne vaut pas ce projet est trop petit)
  • InStream fichiers JPG, GIF ou PNG.

Utilisation:

Disons que déployer cette application web appelé images comme application séparée.

http://www.example.com/images/promotions/promo.jpg

signifie qu'il devrait y avoir un répertoire dans "promotions" avec l'image "promo.jpg" avec images dans cette application web.

PS: Ne demandez pas pourquoi je fais ce conteneur Servlet seule solution qui suce big time

.
  <servlet>
    <description></description>
    <display-name>ImageDisplayServlet</display-name>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <servlet-class>com.example.images.ImageDisplayServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

Oh ya configurer votre Servlet comme ci-dessus pour obtenir les meilleurs résultats: P

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top