web-dev-qa-db-fra.com

XMLHttpRequest POST multipart/form-data

Je souhaite utiliser XMLHttpRequest en JavaScript pour POST un formulaire comprenant un élément input de type de fichier afin d'éviter l'actualisation de la page et d'obtenir du code XML utile.

Je peux soumettre le formulaire sans actualiser la page, en utilisant JavaScript pour définir l'attribut cible du formulaire sur un iframe pour MSIE ou un objet pour Mozilla, mais cela pose deux problèmes. Le problème mineur est que la cible n’est pas conforme au W3C (c’est pourquoi je l’ai définie en JavaScript et non en XHTML). Le problème majeur est que l'événement onload ne se déclenche pas, du moins pas sur Mozilla sous OS X Leopard. De plus, XMLHttpRequest créerait un code de réponse plus joli, car les données renvoyées pourraient être du type XML et non pas limitées à XHTML, comme c'est le cas avec iframe.

La soumission des résultats du formulaire au format HTTP ressemble à ceci: 

Content-Type: multipart/form-data;boundary=<boundary string>
Content-Length: <length>
--<boundary string>
Content-Disposition: form-data, name="<input element name>"

<input element value>
--<boundary string>
Content-Disposition: form-data, name=<input element name>"; filename="<input element value>"
Content-Type: application/octet-stream

<element body>

Comment faire pour que la méthode send de l'objet XMLHttpRequest duplique le flux HTTP ci-dessus?

19
Robin like the bird

Vous pouvez construire vous-même la requête 'multipart/form-data' (pour plus d'informations, visitez http://www.faqs.org/rfcs/rfc2388.html ) puis utilisez la méthode send (c'est-à-dire. xhr.send (your-multipart-form-data)). De même, mais plus facilement, dans Firefox 4+ (également dans Chrome 5+ et Safari 5+), vous pouvez utiliser l'interface FormData qui vous permet de créer de telles requêtes. La méthode send convient au contenu texte, mais si vous souhaitez envoyer des données binaires telles que des images, vous pouvez le faire à l'aide de la méthode sendAsBinary qui a démarré avec Firefox 3.0. Pour plus d'informations sur l'envoi de fichiers via XMLHttpRequest, veuillez vous référer à http://blog.igstan.ro/2009/01/pure-javascript-file-upload.html .

24
Alex Polo

Il n’existe aucun moyen d’accéder à un champ de saisie de fichier à l’aide de javascript. Il n’existe donc pas de solution javascript uniquement pour les envois de fichiers ajax.

Il existe des solutions de contournement comme en utilisant un iframe

L’autre option consisterait à utiliser quelque chose du type SWFUpload ou Google Gears

5
TonyB

Contenu-Disposition: données de formulaire, nom

Vous devez utiliser un point-virgule, comme ceci: Content-Disposition: form-data; prénom

0
Aldekein

Je ne vois pas pourquoi iframe (invisible) implique XHTML et non TOUT contenu. Si vous utilisez une iframe, vous pouvez définir l'événement onreadystatechange et attendre la fin. Ensuite, vous pouvez utiliser frame.window.document.innerHTML (veuillez me corriger) pour obtenir le résultat de la chaîne.

var lFrame = document.getElementById('myframe');
lFrame.onreadystatechange = function()
{
   if (lFrame.readyState == 'complete')
   {
      // your frame is done, get the content...
   }
};
0
helios

je suis confus au sujet de l'événement onload que vous avez spécifié, il se trouve sur la page ou sur l'iframe?, La première réponse est correcte Il n'y a aucun moyen de le faire en utilisant uniquement xmlhttprequest, si ce que vous voulez obtenir en déclenche une partie. Une fois la réponse de la méthode sur iframe vérifiée, il suffit de vérifier si elle contient déjà du contenu ou de ne pas utiliser de script DOM, puis de lancer la méthode.

attacher un événement onload à l'iframe

if(window.attachEvent){
 document.getElementById(iframe).attachEvent('onload', some_method);
}else{
 document.getElementById(iframe).addEventListener('load', some_method, false);
} 
0
Komang

Pour que cela fonctionne, vous devez POST _, ajouter simplement un attribut cible à votre formulaire, dans lequel vous spécifiez l'ID IFrame. Quelque chose comme ça:


<form method="post" target="myiframe" action="handler.php">
...
</form>
<iframe id="myiframe" style="display:none" />
0
mmattax

Voici une méthode à jour utilisant FormData ( doc complet @MDN )

Scénario:

var form = document.querySelector('#myForm');
form.addEventListener("submit", function(e) {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", this.action);
    xhr.addEventListener("load", function(e) {
        // Your callback
    });

    xhr.send(new FormData(this));

    e.preventDefault();
});

(de cette forme de base)

<form id="myForm" action="..." method="POST" enctype="multipart/form-data">
    <input type="file" name="file0">
    <input type="text" name="some-text">
    ...
</form>

Merci encore à Alex Polo pour sa réponse

0
Romuald Brunet