webentwicklung-frage-antwort-db.com.de

JavaScript: Datei hochladen

Angenommen, ich habe dieses Element auf der Seite:

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

Dadurch wird eine Schaltfläche erstellt, mit der die Benutzer der Webseite eine Datei über einen OS-Dialog "Datei öffnen ..." im Browser auswählen können.

Angenommen, der Benutzer klickt auf diese Schaltfläche, wählt eine Datei im Dialogfeld aus und klickt dann auf die Schaltfläche "Ok", um das Dialogfeld zu schließen.

Der ausgewählte Dateiname wird jetzt gespeichert in:

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

Angenommen, der Server verarbeitet mehrteilige POSTs unter der URL "/ upload/image".

Wie sende ich die Datei an "/ upload/image"?

Wie kann ich außerdem auf die Benachrichtigung warten, dass der Upload der Datei abgeschlossen ist?

152
YummyBánhMì

Wenn Sie nicht versuchen, die Datei mit Ajax hochzuladen, senden Sie einfach das Formular an /upload/image.

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

Wenn Sie das Bild im Hintergrund hochladen möchten (z. B. ohne das gesamte Formular zu senden), können Sie Ajax verwenden:

90
Matt Ball

Reine JS

Sie können fetch optional mit wait-try-catch verwenden

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));  
    
    try {
       let r = await fetch('/upload/image', {method: "POST", body: formData}); 
       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)

Old School Ansatz - 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.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>)

ZUSAMMENFASSUNG

  • Auf der Serverseite können Sie den ursprünglichen Dateinamen (und andere Informationen) lesen, die automatisch zur Anforderung hinzugefügt werden.
  • Sie müssen den Anforderungsheader Content-Type NICHT auf multipart/form-data setzen - dies wird automatisch vom Browser festgelegt.
  • Anstelle von /upload/image können Sie auch eine vollständige Adresse wie http://.../upload/image verwenden.
  • Sie können zusätzliche Daten (json) angeben, um z. let user = {name:'john', age:34} auf diese Weise: formData.append("user", JSON.stringify(user));
  • Diese Lösung sollte auf allen gängigen Browsern funktionieren.
38

Wenn Sie tatsächlich eine reine JavaScript-Methode zum Hochladen eines Bildes suchen, finden Sie im folgenden Tutorial aus dem Jahr 2009 eine genaue Anleitung dazu:

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

Ich bin darauf gestoßen, als ich einer Formularübermittlung die Basisauthentifizierung hinzufügen wollte, ohne Cookies zu aktivieren. Z.B. wenn Sie Benutzernamen-/Passwortfelder mit Ihren Dateinamen-, Datei- usw. Feldern haben.

Hoffe das hilft!

24
dwh

Als Schöpfer bin ich voreingenommen;), aber Sie könnten auch in Betracht ziehen, etwas wie https://uppy.io zu verwenden. Es führt das Hochladen von Dateien durch, ohne von der Seite weg zu navigieren, und bietet einige Vorteile wie Drag & Drop, Fortsetzen des Uploads bei Abstürzen des Browsers/unzuverlässigen Netzwerken und Importieren von z. Instagram. Es ist auch Open Source und verlässt sich nicht auf jQuery oder ähnliches.

6
kvz