Javascript XMLHttp-Request – Dateiupload

Datei Upload : Videodateien, Musik, Textdateien, Bilder mit Javascript auf den Server laden

Der XMLHttp-Request ist ein Multitalent: Er führt ein Update der Seite aus, holt Bilder und Daten vom Server und schickt Daten zum Server ohne die Seite neu zu laden. Mit Ajax 1 stand nur ein Event zur Verfügung: onreadystatechange. Ajax 2 beschert uns ein neues Event-Modell mit neuen Events, die eine detailliertere Abfrage der Vorgänge und des Zustands erlauben.

Mit Ajax 2 kann ein Post Back zu einem Ajax-Server auf einer anderen Domain durchgeführt werden – Cross Origin Requests

progress – Fortschrittsbalken

Wie glücklich kleine Fortschritte machen – mit Ajax 2 kommt endlich ein Fortschrittsbalken. HTML5 hat dafür das progress-Tag spendiert, das mit Javascript in Gang gesetzt wird.

Mehrere Dateien laden

Dass die Thumbnails für die geladenen Bilder (zumindest bei kleinen Bildern) hier so schnell erscheinen, liegt natürlich daran, dass sie noch nicht auf den Server geladen sind, sondern noch im Speicher des Browsers liegen. Wenn große Bilddateien mit mehreren Megabyte ausgewählt werden, braucht der Browser sichtbar Zeit, um die Thumbnails zu erstellen.

Der tatsächliche Upload auf den Server beginnt, wenn die Formulardaten mit dem "Laden"-Button abgeschickt wurden.

<form action="…">
   <input type="file" id="file" multiple="true" accept="image/*">
   <button id="startUpload">Laden</button>
   <progress id="progress" value="0" max="100"></progress>
   <span id="msg"></span>
</form>

Ajax: Upload mehrerer Dateien

Die Auswahl mehrerer Dateien für den File-Upload war früher dem File-Upload mit Flash vorbehalten oder einem komplexen Ajax-Ablauf.

In HTML5 hat das input-Tag für den File-Upload ein neues Attribut multiple="true". Ohne großen Aufwand kann Ajax2 mehrere Dateien auf den Server laden.

Mobile Geräte wie Tablet oder Smartphone bieten den Upload von Dateien aus dem Album des Geräts an. multiple="true" funktioniert allerdings nicht, wenn Bilder aus der Kamera geladen werden sollen.

Fotos aus der Kamera werden mit

	<input type="file" accept="image/*" capture="camera" />

geladen. Das funktioniert zurzeit allerdings nur mit Webkit-Browsern (Chrome, Safari).

doStartUpload() lädt die ausgewählten Dateien in den Speicher des Browsers, genauer gesagt, in das Javascript FileReader()-Objekt.

document.getElementById('startUpload').addEventListener ('click',doStartUpload,true);
var msg = document.getElementById('msg');
var progress = document.getElementById('progress');
var targetLocation = "upload.php";

function doStartUpload (e) {
  progress.value = 0;
  msg.innerHTML = '';
  document.querySelector ('#dlist').innerHTML = '';
  var fileElem = document.getElementById('file');
  if (fileElem.files.length == 0) {
    msg.innerHTML = 'Wählen Sie zuerst eine Datei aus';
  } else {
    msg.innerHTML = 'Datei für Übertragung vorbereiten … ';
    var reader = new FileReader();
    reader.onloadend = doUpload;
    reader.readAsArrayBuffer(fileElem.files[0]);
    // Um mal zu sehen, was im Browser landet … 
    for (let i = 0, f; f = fileElem.files [i]; i++ ) {
      document.querySelector ('#dlist').innerHTML += 
        f.size + ' ' +  
        f.type + '<br />'; 
    }
  }
  e.preventDefault();
}

upload.onprogress und onprogress

Ein Fortschrittsbalken für den Upload von Dateien ist ein wichtiges Element der Benutzeroberfläche.

Javascript konnte zwar den Dateinamen, den Dateityp sowie Höhe und Breite des Bildes lesen, aber hatte keinen Zugriff auf die Größe der Datei auf dem lokalen Rechner des Benutzers.

function doUpload(e) {
   var xhr = new XMLHttpRequest();
   xhr.upload.onprogress = function (e) {
      var percentUpload = Math.floor(100*e.loaded / e.total);
      progress.value = percentUpload;
      msg.innerHTML = percentUpload + '% geladen';
   }

   xhr.onerror = function(e) {
      msg.innerHTML = "Ein Fehler ist aufgetreten";
   }

   xhr.open ('POST', targetLocation, true); // XMLRequest an den Server
  
   var bytesToSend = [253, 0, 128, 1],
      bytesArray = new Uint8Array(bytesToSend);

   xhr.setRequestHeader('Content-Type', 'application/octet-stream');
   xhr.send(bytesArray);
}