Back

So erstellen Sie eine Upload-Fortschrittsanzeige mit JavaScript

So erstellen Sie eine Upload-Fortschrittsanzeige mit JavaScript

Das Hochladen von Dateien ohne visuelles Feedback lässt Benutzer im Unklaren darüber, ob überhaupt etwas passiert. Eine Fortschrittsanzeige verwandelt diese Unsicherheit in eine klare, zugängliche Benutzererfahrung, die genau zeigt, wie viel des Uploads bereits abgeschlossen ist.

Dieser Artikel demonstriert, wie Sie eine Echtzeit-Upload-Fortschrittsanzeige mit der XMLHttpRequest-API von JavaScript, semantischen HTML-Elementen und Best Practices für Barrierefreiheit erstellen – eine Lösung, die zuverlässig in allen modernen Browsern funktioniert.

Wichtigste Erkenntnisse

  • XMLHttpRequest bleibt die Standard-API für die Verfolgung des Upload-Fortschritts, da die Fetch-API keine Upload-Progress-Events unterstützt
  • Semantisches HTML mit ARIA-Attributen gewährleistet Barrierefreiheit für alle Benutzer
  • Die Lösung funktioniert in allen modernen Browsern ohne externe Abhängigkeiten
  • Ordnungsgemäße Fehlerbehandlung und Benutzersteuerungen schaffen eine robuste Upload-Erfahrung

Einrichten der HTML-Struktur

Beginnen Sie mit semantischem HTML, das sowohl visuelles als auch barrierefreies Feedback bietet:

<form id="uploadForm">
  <label for="fileInput">Select file to upload:</label>
  <input type="file" id="fileInput" name="file" accept="image/*,application/pdf">
  
  <progress id="uploadProgress" value="0" max="100" aria-label="Upload progress"></progress>
  <span id="progressText" aria-live="polite">0% uploaded</span>
  
  <button type="submit">Upload File</button>
  <button type="button" id="cancelBtn" disabled>Cancel Upload</button>
</form>

Das <progress>-Element bietet native Semantik, die von assistiven Technologien verstanden wird. Der begleitende Prozenttext stellt sicher, dass sich Benutzer nicht ausschließlich auf visuelle Hinweise verlassen müssen. Das Attribut aria-live="polite" gibt Prozentänderungen an Screenreader weiter, ohne andere Inhalte zu unterbrechen.

Warum XMLHttpRequest für Upload-Fortschritt

Während die Fetch-API die meisten modernen HTTP-Anfragen elegant handhabt, stellt sie immer noch keine Upload-Progress-Events bereit. Das XMLHttpRequest-Objekt bleibt das richtige Werkzeug für die Implementierung der Upload-Fortschrittsverfolgung, da es den Event-Handler xhr.upload.onprogress bereitstellt.

Beachten Sie, dass nur synchrones XMLHttpRequest veraltet ist – asynchrones XHR bleibt eine grundlegende, gut unterstützte API, die perfekt für diesen Anwendungsfall geeignet ist.

Implementierung der Upload-Fortschrittsanzeige mit JavaScript

Hier ist die vollständige Implementierung, die Dateiauswahl, Upload-Tracking und Benutzersteuerungen handhabt:

const form = document.getElementById('uploadForm');
const fileInput = document.getElementById('fileInput');
const progressBar = document.getElementById('uploadProgress');
const progressText = document.getElementById('progressText');
const cancelBtn = document.getElementById('cancelBtn');

let currentXHR = null;

form.addEventListener('submit', (e) => {
  e.preventDefault();
  
  const file = fileInput.files[0];
  if (!file) return;
  
  // Validate file size (10MB limit example)
  const maxSize = 10 * 1024 * 1024;
  if (file.size > maxSize) {
    alert('File size exceeds 10MB limit');
    return;
  }
  
  uploadFile(file);
});

function uploadFile(file) {
  const formData = new FormData();
  formData.append('file', file);
  
  currentXHR = new XMLHttpRequest();
  
  // Track upload progress
  currentXHR.upload.onprogress = (event) => {
    if (event.lengthComputable) {
      const percentComplete = Math.round((event.loaded / event.total) * 100);
      updateProgress(percentComplete);
    } else {
      // Handle indeterminate progress
      progressBar.removeAttribute('value');
      progressText.textContent = 'Uploading...';
    }
  };
  
  // Handle completion
  currentXHR.onload = function() {
    if (currentXHR.status === 200) {
      updateProgress(100);
      progressText.textContent = 'Upload complete!';
      resetForm();
    } else {
      handleError('Upload failed: ' + currentXHR.statusText);
    }
  };
  
  // Handle errors
  currentXHR.onerror = () => handleError('Network error occurred');
  currentXHR.onabort = () => handleError('Upload cancelled');
  
  // Send request
  currentXHR.open('POST', '/api/upload', true);
  currentXHR.send(formData);
  
  // Enable cancel button
  cancelBtn.disabled = false;
}

function updateProgress(percent) {
  progressBar.value = percent;
  progressText.textContent = `${percent}% uploaded`;
}

function handleError(message) {
  progressText.textContent = message;
  progressBar.value = 0;
  resetForm();
}

function resetForm() {
  cancelBtn.disabled = true;
  currentXHR = null;
  setTimeout(() => {
    progressBar.value = 0;
    progressText.textContent = '0% uploaded';
  }, 2000);
}

// Cancel upload functionality
cancelBtn.addEventListener('click', () => {
  if (currentXHR) {
    currentXHR.abort();
  }
});

Das Progress-Event verstehen

Das xhr.upload.onprogress-Event bietet drei wichtige Eigenschaften:

  • event.loaded: Bereits hochgeladene Bytes
  • event.total: Gesamtdateigröße in Bytes
  • event.lengthComputable: Boolean, der angibt, ob die Gesamtgröße bekannt ist

Wenn lengthComputable true ist, berechnen Sie den Prozentsatz als (loaded / total) * 100. Wenn false, hat der Server keine Content-Length-Header bereitgestellt, zeigen Sie daher einen unbestimmten Fortschrittsstatus an, indem Sie das value-Attribut des Progress-Elements entfernen.

Styling für eine bessere Benutzererfahrung

Fügen Sie CSS hinzu, um die Upload-Fortschrittsimplementierung visuell klar zu gestalten:

progress {
  width: 100%;
  height: 24px;
  margin: 10px 0;
}

/* Webkit browsers */
progress::-webkit-progress-bar {
  background-color: #f0f0f0;
  border-radius: 4px;
}

progress::-webkit-progress-value {
  background-color: #4CAF50;
  border-radius: 4px;
  transition: width 0.3s ease;
}

/* Firefox */
progress::-moz-progress-bar {
  background-color: #4CAF50;
  border-radius: 4px;
}

#progressText {
  display: block;
  margin-top: 5px;
  font-weight: 600;
}

Serverseitige Überlegungen

Der Server-Endpunkt sollte multipart/form-data-Uploads akzeptieren. Hier ist ein minimales Node.js-Beispiel mit Express und Multer:

const multer = require('multer');
const upload = multer({ dest: 'uploads/' });

app.post('/api/upload', upload.single('file'), (req, res) => {
  // File is available as req.file
  res.json({ success: true, filename: req.file.filename });
});

Für den Produktiveinsatz fügen Sie Dateitypvalidierung, Virenscanning und ordnungsgemäße Speicherhandhabung hinzu (lokales Dateisystem oder Cloud-Dienste wie AWS S3).

Browser-Kompatibilität und Progressive Enhancement

Dieser Ansatz funktioniert in allen modernen Browsern, da XMLHttpRequest Level 2 (das Upload-Fortschritt einschließt) seit folgenden Versionen unterstützt wird:

  • Chrome 7+
  • Firefox 3.5+
  • Safari 5+
  • Edge (alle Versionen)

Bei älteren Browsern funktioniert der Upload weiterhin – Benutzer sehen nur keine Fortschrittsaktualisierungen. Das Formular degradiert elegant zu einem Standard-Datei-Upload.

Fazit

Der Aufbau einer barrierefreien Upload-Fortschrittsanzeige erfordert XMLHttpRequest für Progress-Events, semantisches HTML für die Struktur und durchdachtes JavaScript für die Handhabung verschiedener Upload-Zustände. Diese Implementierung bietet Echtzeit-Feedback, das für alle Benutzer funktioniert, einschließlich derjenigen, die assistive Technologien verwenden, und dabei eine breite Browser-Kompatibilität ohne externe Bibliotheken aufrechterhält.

Häufig gestellte Fragen (FAQs)

Die Fetch-API unterstützt keine Upload-Progress-Events. XMLHttpRequest bietet den Event-Handler xhr.upload.onprogress speziell für die Verfolgung des Upload-Fortschritts, was es zur einzigen praktikablen Option für Echtzeit-Fortschrittsanzeigen macht.

Erstellen Sie separate XMLHttpRequest-Instanzen für jede Datei oder reihen Sie diese sequenziell ein. Verfolgen Sie den individuellen Fortschritt und berechnen Sie den Gesamtfortschritt durch Mittelung der Prozentsätze oder Summierung der geladenen Bytes über alle Dateien hinweg.

Ohne Content-Length-Header gibt event.lengthComputable false zurück. Zeigen Sie einen unbestimmten Fortschrittsstatus an, indem Sie das value-Attribut des Progress-Elements entfernen und generischen Ladetext anstelle von Prozentsätzen anzeigen.

Standard-XMLHttpRequest unterstützt keine fortsetzbaren Uploads. Für diese Funktionalität implementieren Sie gestückelte Uploads mit serverseitiger Unterstützung oder verwenden Sie spezialisierte Bibliotheken, die Dateiaufteilung und Fortsetzungslogik handhaben.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay