CSS, HTML und Javascript mit {stil}

Ajax 2 – Dateien laden mit Fortschrittsbalken

Videodateien, Musik, Textdateien auf den Server laden

Javascript bringt handfeste Verbesserungen des XMLHttp-Requests. 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

Wie glücklich kleine Fortschritte machen – mit HTML5 und Ajax 2 kommt endlich ein Fortschrittsbalken.

progress – 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);
}