IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement Web en Java Discussion :

Comment se passer du multipart/form-data


Sujet :

Développement Web en Java

  1. #1
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut Comment se passer du multipart/form-data
    Bonjour

    J'ai un formulaire qui me permet d'envoyer une image à une Servlet et de la copier dans un dossier sur le disque. Tout marche bien sauf que j'aimerai utiliser la technologie AJAX dans le but de ne pas charger la page lors de l'envoi de l'image. Or, Ajax ne supporte pas le " multipart/form-data", du coup je ne sais pas comment gérer l'envoi des fichiers avec Java sans utiliser le " multipart/form-data".

    Voici le message d'erreur que je reçois:

    javax.servlet.ServletException: org.apache.tomcat.util.http.fileupload.FileUploadBase$InvalidContentTypeException: the request doesn't contain a multipart/form-data or multipart/form-data stream, content type header is text/plain;charset=UTF-8
    at org.apache.catalina.connector.Request.parseParts(Request.java:2811)
    at org.apache.catalina.connector.Request.getParts(Request.java:2665)
    at org.apache.catalina.connector.Request.getPart(Request.java:2835)
    at org.apache.catalina.connector.RequestFacade.getPart(RequestFacade.java:1083)
    Voici ma fonction Ajax:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    $(function() {
    var form = $('#form1');
    form.submit(function () {
     
    $.ajax({
    type: form.attr('method'),
    contentType: false,
    url: form.attr('action'),
    data: form.serialize(),
    success: function (data) {
        var result=data;
    //var result=data.split(" ");
    //var donnee1 = result[0];
    //var donnee2 = result[1];
    $('#result').attr("value",result);
    },
    error: function() {
     alert('La requête n\'a pas abouti');
      }
    });
     
    return false;
    });
    });
    Voici ma méthode de validation de l'image provenant de ma Servlet:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    private String validationImage( HttpServletRequest request, String chemin ) throws FormValidationException {
            /*
             * Récupération du contenu du champ image du formulaire. Il faut ici
             * utiliser la méthode getPart().
             */
            String nomFichier = null;
            InputStream contenuFichier = null;
            try {
                Part part = request.getPart( CHAMP_IMAGE );
                nomFichier = getNomFichier( part );
     
                /*
                 * Si la méthode getNomFichier() a renvoyé quelque chose, il s'agit
                 * donc d'un champ de type fichier (input type="file").
                 */
                if ( nomFichier != null && !nomFichier.isEmpty() ) {
                    /*
                     * Antibug pour Internet Explorer, qui transmet pour une raison
                     * mystique le chemin du fichier local à la machine du client...
                     * 
                     * Ex : C:/dossier/sous-dossier/fichier.ext
                     * 
                     * On doit donc faire en sorte de ne sélectionner que le nom et
                     * l'extension du fichier, et de se débarrasser du superflu.
                     */
                    nomFichier = nomFichier.substring( nomFichier.lastIndexOf( '/' ) + 1 )
                            .substring( nomFichier.lastIndexOf( '\\' ) + 1 );
     
                    /* Récupération du contenu du fichier */
                    contenuFichier = part.getInputStream();
     
                    /* Extraction du type MIME du fichier depuis l'InputStream */
                    MimeUtil.registerMimeDetector( "eu.medsea.mimeutil.detector.MagicMimeMimeDetector" );
                    Collection<?> mimeTypes = MimeUtil.getMimeTypes( contenuFichier );
     
                    /*
                     * Si le fichier est bien une image, alors son en-tête MIME
                     * commence par la chaîne "image"
                     */
                    if ( mimeTypes.toString().startsWith( "image" ) ) {
                        /* Écriture du fichier sur le disque */
                        ecrireFichier( contenuFichier, nomFichier, chemin );
                    } else {
                        throw new FormValidationException( "Le fichier envoyé doit être une image." );
                    }
                }
            } catch ( IllegalStateException e ) {
                /*
                 * Exception retournée si la taille des données dépasse les limites
                 * définies dans la section <multipart-config> de la déclaration de
                 * notre servlet d'upload dans le fichier web.xml
                 */
                e.printStackTrace();
                throw new FormValidationException( "Le fichier envoyé ne doit pas dépasser 1Mo." );
            } catch ( IOException e ) {
                /*
                 * Exception retournée si une erreur au niveau des répertoires de
                 * stockage survient (répertoire inexistant, droits d'accès
                 * insuffisants, etc.)
                 */
                e.printStackTrace();
                throw new FormValidationException( "Erreur de configuration du serveur." );
            } catch ( ServletException e ) {
                /*
                 * Exception retournée si la requête n'est pas de type
                 * multipart/form-data.
                 */
                e.printStackTrace();
                throw new FormValidationException(
                        "Ce type de requête n'est pas supporté, merci d'utiliser le formulaire prévu pour envoyer votre fichier." );
            }
     
            return nomFichier;
        }
    Merci

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    On peut faire du multipart/formdata en ajax, par exemple en JQuery (ici de base) :
    Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    var formData = new FormData();
    formData.append("param", "toto"); // ajouter le paramètre de nom param et de valeur "toto"
     
    $.ajax({
        type: "POST",
        enctype: 'multipart/form-data', 
        url: "http:/machin/truc",
        traditional: true, /* pour avoir les paramètres multivalués en plusieurs paramètres */
        data: formData,
        processData: false,
        contentType: false,
        cache: false, 
        success: function(data, textstatus, xhr) {
        	  /*...*/
        }, 
        fail: function(xhr, textstatus, error) {
             /*...*/
        }
    });

    Pour envoyer des fichiers, le plus simple est d'avoir un form avec des input de type file et d'aller les chercher pour les ajouter au formdata :

    Exemple ou inputFile est un champ input de type file (par exemple récupéré par $.("input[type='file']")
    Code JavaScript : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    $("input[type='file']").each(function(index,inputFile) {
    	 if ( inputFile.files.length!=0 ) { // si fichier sélectionnné
                formData.append(inputFile.name, inputFile.files[0]); // exemple pour un champ monofichier, sinon il faut parcourir le tableau et créer un tableau avec chaque fichier dedans
             } 
    });
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut
    Ok merci, je ne reçois plus de message d'erreur concernant le multipart/formdata par-contre on dirait que mon fichier n'arrive pas à être récupéré par le serveur.
    Au niveau du javascript je reçois le message d'erreur que j'ai défini dans la méthode "error":

    La requête n\'a pas abouti
    Et au niveau du log de netbeans je reçois ceci:

    juil. 12, 2018 9:41:45 AM org.apache.catalina.core.StandardWrapperValve invoke
    GRAVE: "Servlet.service()" pour la servlet AjoutProduit a généré une exception
    java.lang.NullPointerException
    at forms.CreationProduitForm.ecrireFichier(CreationProduitForm.java:298)
    at forms.CreationProduitForm.validationImage(CreationProduitForm.java:193)
    at forms.CreationProduitForm.traiterImage(CreationProduitForm.java:114)
    at forms.CreationProduitForm.creerProduit(CreationProduitForm.java:66)
    at servlets.AjoutProduit.doPost(AjoutProduit.java:55)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:409)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1044)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
    Voici mon fichier test-ajax-upload.js:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    $(function() {
    var form = $('#form1');
    form.submit(function () {
     var formData = new FormData();
    $("input[type='file']").each(function(index,inputFile) {
    	 if ( inputFile.files.length!==0 ) { // si fichier sélectionnné
                formData.append(inputFile.name, inputFile.files[0]); // exemple pour un champ monofichier, sinon il faut parcourir le tableau et créer un tableau avec chaque fichier dedans
             } 
             else
                 {
                     alert('fichier non sélectionné');
                 }
    }); 
     
    $.ajax({
    type: form.attr('method'),
    enctype: 'multipart/form-data',
    url: form.attr('action'),
    data: formData,
    processData: false,
        contentType: false,
        cache: false,
    success: function (data) {
        var result=data;
    //var result=data.split(" ");
    //var donnee1 = result[0];
    //var donnee2 = result[1];
    $('#result').attr("value",result);
    },
    error: function() {
     alert('La requête n\'a pas abouti');
      }
    });
     
    return false;
    });
    });
    Voici mon fichier test4.jsp:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
        <head>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            <title>JSP Page</title>
        </head>
        <body>
            <h1>Hello World!</h1>
            <form name="form1" method="POST" action="produit" id="form1">
     <input type="file" name="image"/>
     <input type="submit" value="Envoyer le fichier" />
     <input type="text" value="" id="result"/>
    </form>
    <progress></progress>
    <script src="js/jquery-1.9.1.min.js"></script>
    <script src="js/test-ajax-upload.js"></script>
        </body>
    </html>
    Et Voici la méthode ecrireFichier:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
     
    public final class CreationProduitForm {
        private static final String CHAMP_CATEGORIE       = "categorie";
        private static final String CHAMP_PRIX    = "prix";
        private static final String CHAMP_DESCRIPTION   = "description";
        private static final String CHAMP_IMAGE     = "image";
     
      ....
     
    /*
         * Méthode utilitaire qui a pour but d'écrire le fichier passé en paramètre
         * sur le disque, dans le répertoire donné et avec le nom donné.
         */
        private void ecrireFichier( InputStream contenuFichier, String nomFichier, String chemin )
                throws FormValidationException {
            /* Prépare les flux. */
            BufferedInputStream entree = null;
            BufferedOutputStream sortie = null;
            try {
                /* Ouvre les flux. */
                entree = new BufferedInputStream( contenuFichier, TAILLE_TAMPON );
                sortie = new BufferedOutputStream( new FileOutputStream( new File( chemin + nomFichier ) ),
                        TAILLE_TAMPON );
     
                /*
                 * Lit le fichier reçu et écrit son contenu dans un fichier sur le
                 * disque.
                 */
                byte[] tampon = new byte[TAILLE_TAMPON];
                int longueur = 0;
                while ( ( longueur = entree.read( tampon ) ) > 0 ) {
                    sortie.write( tampon, 0, longueur );
                }
            } catch ( Exception e ) {
                throw new FormValidationException( "Erreur lors de l'écriture du fichier sur le disque." );
            } finally {
                try {
                    sortie.close();
                } catch ( IOException ignore ) {
                    System.out.println("erreur");
                }
                try {
                    entree.close();
                } catch ( IOException ignore ) {
                }
            }
        }
    }
    Merci

  4. #4
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut
    Finalement ça marche, j'arrive à envoyer l'image au serveur et la copier dans le répertoire c:/fichiers.

    Le problème venait apparement de mon tomcat. En fait dans mes recherches j'avais lu ceci:

    ...Après avoir soumis un tel formulaire, les données envoyées sont dans un format binaire "multipart", et sont disponibles
    dans le corps de la requête POST.
    À ce sujet, une subtilité importante mérite d'être portée à votre attention : ce format de requête n'est pas supporté par les
    versions de Tomcat antérieures à 7.0.6. L'explication de ce comportement réside principalement dans :
    la version de l'API servlet utilisée : ce n'est qu'à partir de Java EE 6 que la version 3.0 du conteneur de servlets a été mise
    en place. L'API en version 2.x ne supporte pas de telles requêtes, elle ne sait gérer que le enctype par défaut ;
    un bug dans les premières éditions de Tomcat 7 : aucun problème en ce qui nous concerne, car les versions récentes ont
    corrigé ce problème.
    Donc j'utilisais apache-tomcat-7.0.50 que j'avais installé en dehors de mon netbeans 7.3.1, du coup j'ai décidé de le remplacer par le tomcat 7.0.34 intégré dans netbeans mais je rencontrais un problème d'authentification. J'ai donc décidé d'utiliser Glassfish, ce qui a résolu mon problème.

    Donc y a t'il réellement un problème avec les versions antérieures à 7.0.6?

    Maintenant mon nouveau problème est comment utiliser la méthode formData et serialize en même temps? Car je voudrais envoyer du texte et de l'image à mon serveur.

    Merci

  5. #5
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    a noter que si tu veux faire du web service attaqué par ton ajax, pour l'upload de fichier, on préfère en général un simple PUT avec le contenu du fichier dans le payload, c'est plus propre que du multipart.

  6. #6
    Membre éclairé
    Inscrit en
    Juin 2005
    Messages
    578
    Détails du profil
    Informations forums :
    Inscription : Juin 2005
    Messages : 578
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    a noter que si tu veux faire du web service attaqué par ton ajax, pour l'upload de fichier, on préfère en général un simple PUT avec le contenu du fichier dans le payload, c'est plus propre que du multipart.
    Ok je n'en ai jamais entendu parler, pourrais-tu me donner un lien pour ça?

    Sinon j'ai pu résoudre mon problème, j'arrive à envoyer du texte et de l'image:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    $(function() {
    var form = $('#form1');
    form.submit(function () {
     var formData = new FormData();
    $("input[type='file']").each(function(index,inputFile) {
    	 if ( inputFile.files.length!==0 ) { // si fichier sélectionnné
                formData.append(inputFile.name, inputFile.files[0]); // exemple pour un champ monofichier, sinon il faut parcourir le tableau et créer un tableau avec chaque fichier dedans
             } 
             else
                 {
                     alert('fichier non sélectionné');
                 }
    }); 
     
    var other_data = $('#form1').serializeArray();
        $.each(other_data,function(key,input){
            formData.append(input.name,input.value);
        });
     
    $.ajax({
    type: form.attr('method'),
    enctype: 'multipart/form-data',
    url: form.attr('action'),
    data: formData,
    processData: false,
        contentType: false,
        cache: false,
    success: function (data) {
        var result=data;
    //var result=data.split(" ");
    //var donnee1 = result[0];
    //var donnee2 = result[1];
    $('#result').attr("value",result);
    },
    error: function() {
     alert('La requête n\'a pas abouti');
      }
    });
     
    return false;
    });
    });
    Merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 11/06/2010, 08h23
  2. Réponses: 2
    Dernier message: 08/05/2009, 18h00
  3. [Servlet] pb multipart/form-data retourne valeur null
    Par Doumeasse38 dans le forum Servlets/JSP
    Réponses: 1
    Dernier message: 12/05/2006, 08h46
  4. [Upload] enctype='multipart/form-data'
    Par shnouf dans le forum Langage
    Réponses: 2
    Dernier message: 28/03/2006, 15h02
  5. [Upload] Upload .jpg |enctype="multipart/form-data"
    Par Funraill.net dans le forum Langage
    Réponses: 4
    Dernier message: 16/01/2006, 17h44

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo