701 votes

Comment télécharger des fichiers vers le serveur à l'aide de JSP/Servlet?

Comment puis-je télécharger des fichiers vers le serveur à l'aide de JSP/Servlet? J'ai essayé ceci:

<form action="upload" method="post">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

Cependant, je ne reçois que le nom de fichier, pas le contenu du fichier. Quand j'ajoute de la enctype="multipart/form-data" de la <form>, alors request.getParameter() retours null.

Au cours de la recherche, je suis tombé sur Apache Commune FileUpload. J'ai essayé ceci:

FileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List items = upload.parseRequest(request); // This line is where it died.

Malheureusement, la servlet a déclenché une exception sans un message clair et la cause. Voici la stacktrace:

SEVERE: Servlet.service() for servlet UploadServlet threw exception
javax.servlet.ServletException: Servlet execution threw an exception
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    at java.lang.Thread.run(Thread.java:637)

1231voto

BalusC Points 498232

Introduction

Pour parcourir et sélectionnez un fichier à télécharger vous avez besoin d'un HTML <input type="file"> champ dans le formulaire. Comme indiqué dans la spécification HTML , vous devez utiliser l' POST méthode et l' enctype attribut de la forme doit être réglé "multipart/form-data".

<form action="upload" method="post" enctype="multipart/form-data">
    <input type="text" name="description" />
    <input type="file" name="file" />
    <input type="submit" />
</form>

Après la soumission de ce formulaire, le fichier binaire de type multipart, les données de formulaire est disponible dans le corps de la requête dans un format différent que lorsque l' enctype n'est pas définie.

Avant de Servlet 3.0, la Servlet API n'a pas en charge en mode natif multipart/form-data. Il prend en charge uniquement le formulaire par défaut enctype d' application/x-www-form-urlencoded. L' request.getParameter() et consorts seraient tous de retour null lors de l'utilisation de plusieurs parties des données de formulaire.

Ne pas manuellement l'analyser!

Vous pouvez, en théorie, d'analyser le corps de la demande vous-même basé sur ServletRequest#getInputStream(). Cependant, c'est une précis et fastidieux travail qui exige la connaissance précise de RFC2388. Vous ne devriez pas essayer de le faire sur votre propre ou copypaste certains endogène de la bibliothèque-moins de code trouvé ailleurs sur Internet. De nombreuses sources en ligne ont échoué dur dans ce, comme roseindia.net. Voir également le téléchargement de fichier pdf. Vous devriez plutôt utiliser un véritable bibliothèque qui est utilisé (et implicitement testé!) par des millions d'utilisateurs depuis des années. Une telle bibliothèque a prouvé sa robustesse.

Lorsque vous n'êtes pas sur de Servlet 3.0 pourtant, l'utilisation d'Apache Commons FileUpload

Si vous n'êtes pas sur de Servlet 3.0 pourtant, la pratique courante est de faire usage de Apache Commons FileUpload pour analyser les multpart formulaire de demandes de données. Il a un excellent Guide de l'Utilisateur et FAQ (passez soigneusement en revue les deux). Il y a aussi le O'Reilly ("cos") MultipartRequest, mais il a quelques (petites) de bugs et n'est pas activement est plus maintenu depuis des années. Je ne vous recommande pas de l'utiliser. Apache Commons FileUpload est toujours activement maintenu et actuellement très mature.

Pour l'utilisation d'Apache Commons FileUpload, vous devez avoir au moins les fichiers suivants dans votre webapp de l' /WEB-INF/lib:

Votre première tentative a échoué, probablement parce que vous avez oublié les communes IO.

Voici un coup d'envoi exemple, comment l' doPost() de votre UploadServlet peut regarder comme lorsque vous utilisez Apache Commons FileUpload:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    try {
        List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
        for (FileItem item : items) {
            if (item.isFormField()) {
                // Process regular form field (input type="text|radio|checkbox|etc", select, etc).
                String fieldname = item.getFieldName();
                String fieldvalue = item.getString();
                // ... (do your job here)
            } else {
                // Process form file field (input type="file").
                String fieldname = item.getFieldName();
                String filename = FilenameUtils.getName(item.getName());
                InputStream filecontent = item.getInputStream();
                // ... (do your job here)
            }
        }
    } catch (FileUploadException e) {
        throw new ServletException("Cannot parse multipart request.", e);
    }

    // ...
}

Sinon, vous pouvez aussi envelopper tout cela dans un Filter qui analyse tout automatiquement et mettre les trucs de retour dans le parametermap de la demande, de sorte que vous pouvez continuer à utiliser request.getParameter() de la manière habituelle, et de récupérer le fichier téléchargé en request.getAttribute(). Vous pouvez trouver un exemple dans cet article de blog.

Lorsque vous êtes déjà en Servlet 3.0 ou plus récent, de l'utilisation des API natives

Si vous êtes déjà sur la nouvelle API Servlet 3.0, vous pouvez simplement utiliser la norme API fournie HttpServletRequest#getPart() pour recueillir l'individu formulaire multipart éléments de données (plus de Servlet 3.0 implémentations de l'utilisation d'Apache Commons FileUpload sous les couvertures pour cela!). C'est un peu moins convenienced que lors de l'utilisation pure Apache Commons FileUpload (un utilitaire de personnalisation de la méthode est nécessaire pour obtenir le nom de fichier), mais il est possible et plus facile à utiliser si vous connaissez déjà le champ de saisie de noms à l'avance, comme vous le feriez avec getParameter(). Aussi, normal les champs de formulaire sont depuis Servlet 3.0 disponible en getParameter() de la manière habituelle.

Première annoter votre servlet avec @MultipartConfig afin de pouvoir reconnaître et d'appuyer multipart/form-data des demandes et d'obtenir ainsi getPart() de travail:

@WebServlet("/upload")
@MultipartConfig
public class UploadServlet extends HttpServlet {
    // ...
}

Ensuite, mettre en œuvre son doPost() comme suit:

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String description = request.getParameter("description"); // Retrieves <input type="text" name="description">
    Part filePart = request.getPart("file"); // Retrieves <input type="file" name="file">
    String filename = getFilename(filePart);
    InputStream filecontent = filePart.getInputStream();
    // ... (do your job here)
}

private static String getFilename(Part part) {
    for (String cd : part.getHeader("content-disposition").split(";")) {
        if (cd.trim().startsWith("filename")) {
            String filename = cd.substring(cd.indexOf('=') + 1).trim().replace("\"", "");
            return filename.substring(filename.lastIndexOf('/') + 1).substring(filename.lastIndexOf('\\') + 1); // MSIE fix.
        }
    }
    return null;
}

Ceci peut également être fait dans une Filter qui fait tout le travail de façon transparente, de sorte que vous pouvez continuer à utiliser l' request.getParameter() de la manière habituelle. Vous pouvez trouver un exemple dans cet article.

Solution de contournement pour GlassFish bug de l' getParameter() encore de retour null

Notez que Glassfish versions antérieures à la version 3.1.2 avait un bug où l' getParameter() encore les retours null. Si vous ciblez un tel conteneur et ne peut pas le mettre à jour, alors vous avez besoin pour extraire la valeur de getPart() plutôt comme suit:

    String description = getValue(request.getPart("description")); // Retrieves <input type="text" name="description">

Avec cette méthode utilitaire:

private static String getValue(Part part) throws IOException {
    BufferedReader reader = new BufferedReader(new InputStreamReader(part.getInputStream(), "UTF-8"));
    StringBuilder value = new StringBuilder();
    char[] buffer = new char[1024];
    for (int length = 0; (length = reader.read(buffer)) > 0;) {
        value.append(buffer, 0, length);
    }
    return value.toString();
}

Espérons que cela aide tous :)

13voto

chepe lucho Points 704

Sans composant ou d'une Bibliothèque externe dans Tomcat 6 o 7

Permettant de Télécharger dans le web.xml fichier:

http://joseluisbz.wordpress.com/2014/01/17/manually-installing-php-tomcat-and-httpd-lounge/#Enabling%20File%20Uploads.

<servlet>
    <servlet-name>jsp</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
    <multipart-config>
      <max-file-size>3145728</max-file-size>
      <max-request-size>5242880</max-request-size>
    </multipart-config>
    <init-param>
        <param-name>fork</param-name>
        <param-value>false</param-value>
    </init-param>
    <init-param>
        <param-name>xpoweredBy</param-name>
        <param-value>false</param-value>
    </init-param>
    <load-on-startup>3</load-on-startup>
</servlet>

COMME VOUS POUVEZ LE VOIR:

    <multipart-config>
      <max-file-size>3145728</max-file-size>
      <max-request-size>5242880</max-request-size>
    </multipart-config>

Le téléchargement de Fichiers à l'aide de JSP. Fichiers:

Dans le fichier html

<form method="post" enctype="multipart/form-data" name="Form" >

  <input type="file" name="fFoto" id="fFoto" value="" /></td>
  <input type="file" name="fResumen" id="fResumen" value=""/>

Dans le Fichier JSP ou Servlet

    InputStream isFoto = request.getPart("fFoto").getInputStream();
    InputStream isResu = request.getPart("fResumen").getInputStream();
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    byte buf[] = new byte[8192];
    int qt = 0;
    while ((qt = isResu.read(buf)) != -1) {
      baos.write(buf, 0, qt);
    }
    String sResumen = baos.toString();

Modifier votre code de la servlet exigences, comme max-taille de fichier, max-demande-de la taille et d'autres options que vous pouvez définir...

11voto

Pranav Points 128

Vous avez besoin de l' common-io.1.4.jar fichier à inclure dans votre lib répertoire, ou si vous travaillez dans n'importe quel éditeur, comme NetBeans, alors vous devez aller dans les propriétés du projet et il suffit d'ajouter le fichier JAR et vous sera fait.

Pour obtenir l' common.io.jar le fichier simplement google ou tout simplement aller à l'Apache Tomcat site web où vous aurez la possibilité de télécharger gratuitement ce fichier. Mais n'oubliez pas une chose: télécharger le binaire fichier ZIP si vous êtes un utilisateur de Windows.

9voto

Je suis en Utilisant la commune de Servlet pour chaque Formulaire Html si elle a des pièces jointes ou non. Cette Servlet renvoie une TreeMap où les clés sont les jsp nom des Paramètres et les valeurs sont les Entrées de l'Utilisateur et enregistre toutes les pièces jointes en fixe répertoire et, plus tard, vous renommez le répertoire de votre choix.Ici, les Connexions est notre interface personnalisée d'avoir l'objet de connexion. Je pense que cela va vous aider

public class ServletCommonfunctions extends HttpServlet implements
        Connections {

    private static final long serialVersionUID = 1L;

    public ServletCommonfunctions() {}

    protected void doPost(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            IOException {}

    public SortedMap<String, String> savefilesindirectory(
            HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        // Map<String, String> key_values = Collections.synchronizedMap( new
        // TreeMap<String, String>());
        SortedMap<String, String> key_values = new TreeMap<String, String>();
        String dist = null, fact = null;
        PrintWriter out = response.getWriter();
        File file;
        String filePath = "E:\\FSPATH1\\2KL06CS048\\";
        System.out.println("Directory Created   ????????????"
            + new File(filePath).mkdir());
        int maxFileSize = 5000 * 1024;
        int maxMemSize = 5000 * 1024;
        // Verify the content type
        String contentType = request.getContentType();
        if ((contentType.indexOf("multipart/form-data") >= 0)) {
            DiskFileItemFactory factory = new DiskFileItemFactory();
            // maximum size that will be stored in memory
            factory.setSizeThreshold(maxMemSize);
            // Location to save data that is larger than maxMemSize.
            factory.setRepository(new File(filePath));
            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload(factory);
            // maximum file size to be uploaded.
            upload.setSizeMax(maxFileSize);
            try {
                // Parse the request to get file items.
                @SuppressWarnings("unchecked")
                List<FileItem> fileItems = upload.parseRequest(request);
                // Process the uploaded file items
                Iterator<FileItem> i = fileItems.iterator();
                while (i.hasNext()) {
                    FileItem fi = (FileItem) i.next();
                    if (!fi.isFormField()) {
                        // Get the uploaded file parameters
                        String fileName = fi.getName();
                        // Write the file
                        if (fileName.lastIndexOf("\\") >= 0) {
                            file = new File(filePath
                                + fileName.substring(fileName
                                        .lastIndexOf("\\")));
                        } else {
                            file = new File(filePath
                                + fileName.substring(fileName
                                        .lastIndexOf("\\") + 1));
                        }
                        fi.write(file);
                    } else {
                        key_values.put(fi.getFieldName(), fi.getString());
                    }
                }
            } catch (Exception ex) {
                System.out.println(ex);
            }
        }
        return key_values;
    }
}

6voto

Une autre source de ce problème se produit si vous utilisez Geronimo avec son Tomcat intégré. Dans ce cas, après un nombre d'itérations de l'essai commons-io et commons fileupload, le problème se pose à partir d'un chargeur de classe parent de la manipulation de la chambre des communes-xxx pots. Ce qui doit être évité. L'accident est survenu toujours à:

fileItems = uploader.parseRequest(request);

Notez que la Liste type de fileItems a changé avec la version actuelle de commons fileupload être spécifiquement List<FileItem> contrairement aux versions précédentes où il était générique List.

J'ai ajouté le code source pour commons fileupload et commons-io dans mon projet Eclipse à la trace de l'erreur et a finalement obtenu quelques indications. Tout d'abord, l'exception est de type Throwable pas l'déclaré FileIOException ni même d'Exception (ils ne seront pas pris au piège). Deuxièmement, le message d'erreur est obfuscatory en ce qu'elle indique la classe n'est pas trouvé, parce que axis2 ne pouvait pas trouver commons-io. Axis2 n'est pas utilisé dans mon projet, mais il existe un dossier dans le référentiel Geronimo sous-répertoire dans le cadre d'une installation standard.

Enfin, j'ai trouvé 1 place, qui a posé une solution qui a résolu mon problème. Vous devez cacher les pots de parent loader dans le plan de déploiement. Ceci a été mis en geronimo-web.xml avec mon fichier complet illustré ci-dessous.

Pasted from <http://osdir.com/ml/user-geronimo-apache/2011-03/msg00026.html> 



<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<web:web-app xmlns:app="http://geronimo.apache.org/xml/ns/j2ee/application-2.0" xmlns:client="http://geronimo.apache.org/xml/ns/j2ee/application-client-2.0" xmlns:conn="http://geronimo.apache.org/xml/ns/j2ee/connector-1.2" xmlns:dep="http://geronimo.apache.org/xml/ns/deployment-1.2" xmlns:ejb="http://openejb.apache.org/xml/ns/openejb-jar-2.2" xmlns:log="http://geronimo.apache.org/xml/ns/loginconfig-2.0" xmlns:name="http://geronimo.apache.org/xml/ns/naming-1.2" xmlns:pers="http://java.sun.com/xml/ns/persistence" xmlns:pkgen="http://openejb.apache.org/xml/ns/pkgen-2.1" xmlns:sec="http://geronimo.apache.org/xml/ns/security-2.0" xmlns:web="http://geronimo.apache.org/xml/ns/j2ee/web-2.0.1">
    <dep:environment>
        <dep:moduleId>
            <dep:groupId>DataStar</dep:groupId>
            <dep:artifactId>DataStar</dep:artifactId>
            <dep:version>1.0</dep:version>
            <dep:type>car</dep:type>
        </dep:moduleId>

<!--Don't load commons-io or fileupload from parent classloaders-->
        <dep:hidden-classes>
            <dep:filter>org.apache.commons.io</dep:filter>
            <dep:filter>org.apache.commons.fileupload</dep:filter>
        </dep:hidden-classes>
        <dep:inverse-classloading/>        


    </dep:environment>
    <web:context-root>/DataStar</web:context-root>
</web:web-app>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X