Drag-and-Drop-Datei-Upload in React implementieren
Drag-and-Drop-Datei-Uploads verbessern die Nutzererfahrung, indem sie eine intuitive Möglichkeit bieten, in Webanwendungen mit Dateien umzugehen. In diesem Beitrag verwenden wir die gut unterstützte Bibliothek react-dropzone, um eine robuste, typsichere Komponente für Datei-Uploads in React zu erstellen.
Das Projekt einrichten
Verwenden Sie ein bestehendes React-TypeScript-Projekt mit einem Bundler. Aktivieren Sie
allowImportingTsExtensions und noEmit in dessen TypeScript-Konfiguration
für die expliziten Importe von .ts und .tsx
weiter unten; die JavaScript-Ausgabe übernimmt der Bundler.
Installieren Sie zunächst die erforderliche Abhängigkeit mit npm oder yarn:
npm install react-dropzone
# Or
yarn add react-dropzone
Eine TypeScript-Komponente für Datei-Uploads erstellen
Nachfolgend finden Sie ein vollständiges Beispiel für eine Drag-and-Drop-Komponente für
Datei-Uploads, die mit React und TypeScript umgesetzt ist. Diese Komponente nutzt react-dropzone,
um Dateiauswahl, Validierung und Fehlerbehandlung zu steuern. Speichern Sie sie als
DragAndDropUpload.tsx. Der Callback onFilesSelected meldet akzeptierte
Auswahlen, keine abgeschlossenen Netzwerk-Uploads; react-dropzone lädt Dateien nicht selbst hoch.
import React, { useCallback, useState } from 'react'
import { useDropzone, type FileRejection } from 'react-dropzone'
interface UploadProps {
onFilesSelected?: (files: File[]) => void
maxFiles?: number
maxSize?: number
}
const DragAndDropUpload: React.FC<UploadProps> = ({
onFilesSelected,
maxFiles = 1,
maxSize = 5242880, // 5MB
}) => {
const [files, setFiles] = useState<File[]>([])
const [uploadError, setUploadError] = useState<string | null>(null)
const onDropAccepted = useCallback((acceptedFiles: File[]) => {
setFiles(acceptedFiles)
setUploadError(null)
if (onFilesSelected) {
onFilesSelected(acceptedFiles)
}
}, [onFilesSelected])
const onDropRejected = useCallback((fileRejections: FileRejection[]) => {
const errors = fileRejections.map(
(rejection) => `${rejection.file.name}: ${rejection.errors[0].message}`
)
setUploadError(errors.join('\n'))
}, [])
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDropAccepted,
onDropRejected,
maxFiles,
maxSize,
accept: {
'image/*': ['.jpeg', '.jpg', '.png', '.gif'],
'application/pdf': ['.pdf'],
},
})
return (
<div className="upload-container">
<div
{...getRootProps()}
className={`dropzone ${isDragActive ? 'active' : ''}`}
>
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop the files here</p>
) : (
<p>Drag and drop files here, or click to select files</p>
)}
</div>
{uploadError && <div className="error-message">{uploadError}</div>}
{files.length > 0 && (
<div className="file-list">
<h4>Selected Files:</h4>
<ul>
{files.map((file) => (
<li key={file.name}>
{file.name} - {(file.size / 1024).toFixed(2)} KB
</li>
))}
</ul>
</div>
)}
</div>
)
}
export default DragAndDropUpload
Datei-Uploads verarbeiten
Diese Funktion zeigt, wie Sie Datei-Uploads mit der Fetch API und einer sauberen Fehlerbehandlung
verarbeiten. Sie wandelt die ausgewählten Dateien in ein FormData-Objekt um und sendet sie an Ihren
Backend-API-Endpunkt. Speichern Sie den benannten Export weiter unten in
uploadFiles.ts. Dieses Beispiel setzt voraus, dass
/api/upload wiederholte Multipart-Felder mit dem Namen
files akzeptiert und nach deren Annahme einen 2xx-Status zurückgibt.
Clientseitige Typ- und Größenfilter sind Usability-Prüfungen; validieren Sie Inhalt, Größe und
Autorisierung erneut auf dem Server.
export async function uploadFiles(files: File[]): Promise<void> {
const formData = new FormData()
for (const file of files) {
formData.append('files', file)
}
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
})
if (!response.ok) {
throw new Error(`Upload failed (HTTP ${response.status})`)
}
}
Die Komponente gestalten
Die folgenden CSS-Stile sorgen für ein klares und responsives Design der Upload-Komponente. Passen Sie diese Stile bei Bedarf an Ihre Anwendung an.
.upload-container {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.dropzone {
border: 2px dashed #0087f7;
border-radius: 4px;
padding: 20px;
text-align: center;
background: #f8f9fa;
cursor: pointer;
transition: all 0.3s ease;
}
.dropzone.active {
border-color: #00e676;
background: #e3f2fd;
}
.error-message {
color: #d32f2f;
margin-top: 10px;
padding: 10px;
background: #ffebee;
border-radius: 4px;
}
.file-list {
margin-top: 20px;
}
.file-list ul {
list-style: none;
padding: 0;
}
.file-list li {
padding: 8px;
background: #f5f5f5;
margin-bottom: 8px;
border-radius: 4px;
}
Fortgeschrittene Datei-Uploads mit Uppy
Für Projekte, die fortgeschrittene Funktionen wie die Verfolgung des Upload-Fortschritts, Chunked Uploads oder fortsetzbare Uploads benötigen, ist Uppy eine ausgezeichnete Alternative. Das folgende Snippet zeigt, wie Sie Uppy (Version 4.x) in React einbinden. Dieses Snippet rendert lediglich das Dashboard zur Dateiauswahl. Fügen Sie ein Uploader-Plugin wie Tus samt dessen Server-Endpunkt hinzu, um Dateien zu übertragen. Verwenden Sie in einem bestehenden Uppy-4-Projekt zueinander passende Uppy-Paketversionen.
import Uppy from '@uppy/core'
import { Dashboard } from '@uppy/react'
import '@uppy/core/dist/style.min.css'
import '@uppy/dashboard/dist/style.min.css'
const uppy = new Uppy()
function UppyUploader() {
return <Dashboard uppy={uppy} />
}
export default UppyUploader
Uppy baut auf modernen Webstandards auf und funktioniert nahtlos mit React, was es zu einer starken Wahl für komplexe Datei-Uploads macht.
Barrierefreiheit und mobile Aspekte
Berücksichtigen Sie bei der Umsetzung von Drag-and-Drop-Datei-Uploads die folgenden Punkte, um auf allen Geräten eine hervorragende Nutzererfahrung sicherzustellen:
- Stellen Sie sicher, dass der Ablagebereich per Tastatur bedienbar ist, indem Sie bei Bedarf Fokus-Stile oder Attribute ergänzen.
- Verwenden Sie klare und knappe Hinweise, damit Nutzer verstehen, wie sie mit der Komponente interagieren.
- Testen Sie den Ablagebereich auf Mobilgeräten, um zu prüfen, ob Fallback-Verhalten (etwa die Dateiauswahl per Tippen) zuverlässig funktioniert.
- Erwägen Sie, ARIA-Attribute wie
aria-labelzu ergänzen, um die Zugänglichkeit für Screenreader zu verbessern.
Anwendungsbeispiel
Binden Sie die Komponente DragAndDropUpload wie unten gezeigt in Ihre Anwendung ein. In diesem
Beispiel verarbeitet die übergeordnete Komponente die Datei-Uploads, indem sie nach Abschluss der
Dateiauswahl die Funktion uploadFiles aufruft.
import React from 'react'
import DragAndDropUpload from './DragAndDropUpload.tsx'
import { uploadFiles } from './uploadFiles.ts'
const App: React.FC = () => {
const handleFilesSelected = async (files: File[]) => {
try {
await uploadFiles(files)
console.log('Upload completed')
} catch (error) {
console.error('Upload failed:', error)
}
}
return (
<div>
<h1>File Upload</h1>
<DragAndDropUpload
onFilesSelected={handleFilesSelected}
maxFiles={5}
maxSize={5242880}
/>
</div>
)
}
export default App
Fazit
In diesem Beitrag haben wir mit react-dropzone eine robuste, typsichere Drag-and-Drop-Komponente für Datei-Uploads erstellt. Wir haben die Einrichtung des Projekts, die Umsetzung von Dateivalidierung und Fehlerbehandlung sowie die Gestaltung der Komponente behandelt. Außerdem haben wir gezeigt, wie sich Uppy für fortgeschrittene Upload-Funktionen einbinden lässt, und Tipps für Barrierefreiheit und Mobilfreundlichkeit gegeben.
Für fortgeschrittene Funktionen wie die Verfolgung des Upload-Fortschritts, Chunked Uploads und fortsetzbare Uploads bietet sich Uppy an – ein leistungsstarker Open-Source-Dateiuploader, der von Transloadit entwickelt wird (https://uppy.io).
