250 votes

JavaScript : Télécharger le fichier

Disons que j'ai cet élément sur la page :

<input id="image-file" type="file" />

Cela créera un bouton qui permettra aux utilisateurs de la page Web de sélectionner un fichier via une boîte de dialogue OS "Fichier ouvert..." dans le navigateur.

Supposons que l'utilisateur clique sur ledit bouton, sélectionne un fichier dans la boîte de dialogue, puis clique sur le bouton "Ok" pour fermer la boîte de dialogue.

Le nom du fichier sélectionné est maintenant stocké dans :

document.getElementById("image-file").value

Supposons maintenant que le serveur gère les POST en plusieurs parties à l'URL "/upload/image".

Comment envoyer le fichier à "/upload/image" ?

De plus, comment puis-je écouter la notification indiquant que le fichier a fini d'être téléchargé ?

2 votes

JavaScript ne gère pas les téléchargements, car il est côté serveur. Le script côté serveur va recevoir le fichier, et ensuite le déplacer. Pour php, du dossier temporaire au dossier désiré.

0 votes

22 votes

Voté pour rouvrir le site parce que la question porte sur POJS (plain old javascript) et non sur jQuery.

192voto

Kamil Kiełczewski Points 6496

Pure JS

Vous pouvez utiliser aller chercher éventuellement avec await-try-catch

let photo = document.getElementById("image-file").files[0];
let formData = new FormData();

formData.append("photo", photo);
fetch('/upload/image', {method: "POST", body: formData});

async function SavePhoto(inp) 
{
    let user = { name:'john', age:34 };
    let formData = new FormData();
    let photo = inp.files[0];      

    formData.append("photo", photo);
    formData.append("user", JSON.stringify(user)); 

    const ctrl = new AbortController()    // timeout
    setTimeout(() => ctrl.abort(), 5000);

    try {
       let r = await fetch('/upload/image', 
         {method: "POST", body: formData, signal: ctrl.signal}); 
       console.log('HTTP response code:',r.status); 
    } catch(e) {
       console.log('Huston we have problem...:', e);
    }

}

<input id="image-file" type="file" onchange="SavePhoto(this)" >
<br><br>
Before selecting the file open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>

<br><br>
(in stack overflow snippets there is problem with error handling, however in <a href="https://jsfiddle.net/Lamik/b8ed5x3y/5/">jsfiddle version</a> for 404 errors 4xx/5xx are <a href="https://stackoverflow.com/a/33355142/860099">not throwing</a> at all but we can read response status which contains code)

Approche de la vieille école - xhr

let photo = document.getElementById("image-file").files[0];  // file from input
let req = new XMLHttpRequest();
let formData = new FormData();

formData.append("photo", photo);                                
req.open("POST", '/upload/image');
req.send(formData);

function SavePhoto(e) 
{
    let user = { name:'john', age:34 };
    let xhr = new XMLHttpRequest();
    let formData = new FormData();
    let photo = e.files[0];      

    formData.append("user", JSON.stringify(user));   
    formData.append("photo", photo);

    xhr.onreadystatechange = state => { console.log(xhr.status); } // err handling
    xhr.timeout = 5000;
    xhr.open("POST", '/upload/image'); 
    xhr.send(formData);
}

<input id="image-file" type="file" onchange="SavePhoto(this)" >
<br><br>
Choose file and open chrome console > network tab to see the request details.
<br><br>
<small>Because in this example we send request to https://stacksnippets.net/upload/image the response code will be 404 ofcourse...</small>

<br><br>
(the stack overflow snippets, has some problem with error handling - the xhr.status is zero (instead of 404) which is similar to situation when we run script from file on <a href="https://stackoverflow.com/a/10173639/860099">local disc</a> - so I provide also js fiddle version which shows proper http error code <a href="https://jsfiddle.net/Lamik/k6jtq3uh/2/">here</a>)

RÉSUMÉ

  • Côté serveur, vous pouvez lire le nom du fichier original (et d'autres informations) qui est automatiquement inclus dans la requête par le navigateur dans le champ filename paramètre formData.
  • Il n'est pas nécessaire de définir l'en-tête de la demande Content-Type à multipart/form-data - ceci sera défini automatiquement par le navigateur (qui comprendra l'obligation boundary paramètre ).
  • Au lieu de /upload/image vous pouvez utiliser l'adresse complète comme http://.../upload/image (bien sûr, les deux adresses sont arbitraires et dépendent du serveur - et même situation avec le paramètre method - généralement sur les serveurs, "POST" est utilisé pour le téléchargement de fichiers, mais parfois "PUT" ou autre peut être utilisé).
  • Si vous souhaitez envoyer de nombreux fichiers en une seule demande, utilisez la fonction multiple attribut : <input multiple type=... /> et attachez tous les fichiers choisis au formData de la même manière (par exemple photo2=...files[2]; ... formData.append("photo2", photo2); )
  • Vous pouvez inclure des données supplémentaires (json) à la demande, par exemple. let user = {name:'john', age:34} de cette façon : formData.append("user", JSON.stringify(user));
  • Vous pouvez définir le délai d'attente : pour fetch en utilisant AbortController pour l'ancienne approche par xhr.timeout= milisec
  • Ces solutions devraient fonctionner sur tous les principaux navigateurs.

105voto

Matt Ball Points 165937

À moins que vous n'essayiez de télécharger le fichier en utilisant ajax, il suffit de soumettre le formulaire à /upload/image .

<form enctype="multipart/form-data" action="/upload/image" method="post">
    <input id="image-file" type="file" />
</form>

Si vous souhaitez télécharger l'image en arrière-plan (par exemple, sans soumettre le formulaire entier), vous pouvez utiliser l'ajax :

0 votes

Ou une iframe de taille 0x0 avec un téléchargeur d'images script à l'intérieur de son src="" et y envoyer le formulaire en utilisant target="iframeId" en lisant le résultat sur l'événement .load de l'iframe src qui peut être lié en utilisant jQuery par exemple.

15 votes

Il est en fait possible d'upvoter via Javascript et Ajax de nos jours : stackoverflow.com/a/10811427/694469 (Je n'ai pas voté à la baisse).

43 votes

@KajMagnus, vous vouliez probablement dire 'upload' mais avez accidentellement dit 'upvote'.

23voto

dwh Points 91

Si vous cherchez en fait un moyen purement javascript de télécharger une image, le tutoriel suivant, qui date de 2009, vous expliquera exactement comment faire :

http://igstan.ro/posts/2009-01-11-ajax-file-upload-with-pure-javascript.html

J'ai rencontré ce problème lorsque j'ai voulu ajouter une authentification de base à la soumission d'un formulaire, sans activer les cookies. Par exemple, lorsque vous avez des champs nom d'utilisateur/mot de passe avec vos champs nom de fichier, fichier, etc.

J'espère que cela vous aidera !

2voto

Ethan O'Brien Points 115

J'ai essayé de le faire pendant un certain temps et aucune de ces réponses n'a fonctionné pour moi. Voici comment j'ai procédé.

J'avais un fichier de sélection et un bouton d'envoi

<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>

Ensuite, dans mon code javascript, je mets ceci

function doupload() {
    let data = document.getElementById("file").files[0];
    let entry = document.getElementById("file").files[0];
    console.log('doupload',entry,data)
    fetch('uploads/' + encodeURIComponent(entry.name), {method:'PUT',body:data});
    alert('your file has been uploaded');
    location.reload();
};

Si vous aimez StackSnippets...

function doupload() {
    let data = document.getElementById("file").files[0];
    let entry = document.getElementById("file").files[0];
    console.log('doupload',entry,data)
    fetch('uploads/' + encodeURIComponent(entry.name), {method:'PUT',body:data});
    alert('your file has been uploaded');
};

<input type="file" name="file" id="file">
<button onclick="doupload()" name="submit">Upload File</button>

En PUT est légèrement différente de la méthode POST méthode. Dans ce cas, dans le serveur web pour chrome, la méthode POST n'est pas mise en œuvre.

Testé avec le serveur web pour chrome - https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb?hl=en

Note- Lorsque vous utilisez le serveur web pour chrome, vous devez aller dans les options avancées et cocher l'option 'activer le téléchargement de fichiers'. Si vous ne le faites pas, vous obtiendrez une erreur pour non autorisé.

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