0
# File Management
1
2
Handle file selection, metadata editing, and file operations within the dashboard.
3
4
## Capabilities
5
6
### Add Files
7
8
Add files to the uploader with automatic metadata detection and validation.
9
10
```typescript { .api }
11
/**
12
* Add files to the uploader
13
* Handles file validation, metadata extraction, and error handling
14
* @param files - Array of File objects to add
15
*/
16
addFiles(files: File[]): void;
17
```
18
19
**Usage Examples:**
20
21
```typescript
22
import Dashboard from "@uppy/dashboard";
23
24
const dashboard = uppy.getPlugin("Dashboard") as Dashboard;
25
26
// Add files from input element
27
const fileInput = document.getElementById("file-input") as HTMLInputElement;
28
fileInput.addEventListener("change", (event) => {
29
const files = Array.from(event.target.files || []);
30
dashboard.addFiles(files);
31
});
32
33
// Add files from drag and drop
34
function handleDrop(event: DragEvent) {
35
event.preventDefault();
36
const files = Array.from(event.dataTransfer?.files || []);
37
dashboard.addFiles(files);
38
}
39
40
// Add files programmatically
41
async function addFromCustomSource() {
42
const customFiles = await fetchFilesFromAPI();
43
const fileObjects = customFiles.map(data => new File([data.blob], data.name));
44
dashboard.addFiles(fileObjects);
45
}
46
```
47
48
**Behavior:**
49
- Creates file descriptors with source, name, type, and data
50
- Extracts relative path metadata for directory uploads
51
- Validates files against Uppy restrictions
52
- Logs file addition events
53
- Handles and logs any validation errors
54
55
### Save File Card
56
57
Save metadata for a specific file and close the file card interface.
58
59
```typescript { .api }
60
/**
61
* Save file metadata
62
* Updates file metadata and closes file card interface
63
* @param meta - Metadata object to save
64
* @param fileID - ID of the file to update
65
*/
66
saveFileCard(meta: Meta, fileID: string): void;
67
```
68
69
**Usage Examples:**
70
71
```typescript
72
// Save file metadata from form
73
function saveFileMetadata(fileId: string, formData: FormData) {
74
const metadata = {
75
name: formData.get("title") as string,
76
caption: formData.get("caption") as string,
77
altText: formData.get("altText") as string
78
};
79
80
dashboard.saveFileCard(metadata, fileId);
81
}
82
83
// Save metadata with validation
84
function saveWithValidation(fileId: string, metadata: any) {
85
// Validate required fields
86
const requiredFields = uppy.opts.restrictions.requiredMetaFields || [];
87
const missing = requiredFields.filter(field => !metadata[field]);
88
89
if (missing.length > 0) {
90
console.error("Missing required fields:", missing);
91
return;
92
}
93
94
dashboard.saveFileCard(metadata, fileId);
95
}
96
97
// Programmatic metadata saving
98
uppy.on("file-added", (file) => {
99
// Auto-populate metadata for certain file types
100
if (file.type?.startsWith("image/")) {
101
const autoMetadata = {
102
altText: `Image: ${file.name}`,
103
category: "image"
104
};
105
dashboard.saveFileCard(autoMetadata, file.id);
106
}
107
});
108
```
109
110
**Behavior:**
111
- Calls `uppy.setFileMeta()` to update file metadata
112
- Calls `toggleFileCard(false, fileID)` to close the file card
113
- Updates dashboard state to hide file card interface
114
115
### File Card Management
116
117
Control the display and interaction with individual file metadata cards.
118
119
```typescript { .api }
120
/**
121
* Toggle file card visibility for specific file
122
* @param show - Whether to show or hide the file card
123
* @param fileID - ID of the file to show card for
124
*/
125
private toggleFileCard(show: boolean, fileID: string): void;
126
```
127
128
**File Card State:**
129
130
```typescript { .api }
131
/**
132
* File card related state properties
133
*/
134
interface FileCardState {
135
/** File ID for which card is shown, null if no card is active */
136
fileCardFor: string | null;
137
/** Whether file editor is currently shown */
138
showFileEditor: boolean;
139
/** Active overlay type */
140
activeOverlayType: 'FileCard' | 'FileEditor' | null;
141
}
142
```
143
144
### Metadata Fields Configuration
145
146
Configure metadata fields for file information collection.
147
148
```typescript { .api }
149
/**
150
* Metadata field configuration
151
*/
152
interface MetaField {
153
/** Unique field identifier */
154
id: string;
155
/** Display name for the field */
156
name: string;
157
/** Placeholder text for input field */
158
placeholder?: string;
159
/** Custom render function for field */
160
render?: (field: FieldRenderOptions, h: PreactRender) => VNode<any>;
161
}
162
163
/**
164
* Field render options passed to custom render functions
165
*/
166
interface FieldRenderOptions {
167
/** Current field value */
168
value: string;
169
/** Function to update field value */
170
onChange: (newVal: string) => void;
171
/** CSS classes for field styling */
172
fieldCSSClasses: { text: string };
173
/** Whether field is required */
174
required: boolean;
175
/** Form identifier */
176
form: string;
177
}
178
```
179
180
**Metadata Configuration Examples:**
181
182
```typescript
183
// Static metadata fields
184
uppy.use(Dashboard, {
185
metaFields: [
186
{
187
id: "title",
188
name: "Title",
189
placeholder: "Enter file title"
190
},
191
{
192
id: "description",
193
name: "Description",
194
placeholder: "Describe this file"
195
},
196
{
197
id: "tags",
198
name: "Tags",
199
placeholder: "Comma-separated tags"
200
}
201
]
202
});
203
204
// Dynamic metadata fields based on file type
205
uppy.use(Dashboard, {
206
metaFields: (file) => {
207
const baseFields = [
208
{ id: "title", name: "Title", placeholder: "Enter title" }
209
];
210
211
if (file.type?.startsWith("image/")) {
212
return [
213
...baseFields,
214
{ id: "altText", name: "Alt Text", placeholder: "Describe the image" },
215
{ id: "caption", name: "Caption" }
216
];
217
} else if (file.type?.startsWith("video/")) {
218
return [
219
...baseFields,
220
{ id: "transcript", name: "Transcript" },
221
{ id: "duration", name: "Duration" }
222
];
223
}
224
225
return baseFields;
226
}
227
});
228
229
// Custom field rendering
230
uppy.use(Dashboard, {
231
metaFields: [
232
{
233
id: "priority",
234
name: "Priority",
235
render: (field, h) => {
236
return h('select', {
237
value: field.value,
238
onChange: (e) => field.onChange(e.target.value),
239
className: field.fieldCSSClasses.text
240
}, [
241
h('option', { value: '' }, 'Select priority'),
242
h('option', { value: 'low' }, 'Low'),
243
h('option', { value: 'medium' }, 'Medium'),
244
h('option', { value: 'high' }, 'High')
245
]);
246
}
247
}
248
]
249
});
250
```
251
252
### File Events
253
254
Events related to file management operations.
255
256
```typescript { .api }
257
/**
258
* File management events
259
*/
260
interface DashboardFileEvents<M extends Meta, B extends Body> {
261
/** Emitted when file card editing starts */
262
"dashboard:file-edit-start": (file?: UppyFile<M, B>) => void;
263
/** Emitted when file card editing completes */
264
"dashboard:file-edit-complete": (file?: UppyFile<M, B>) => void;
265
}
266
```
267
268
**Event Usage Examples:**
269
270
```typescript
271
// Track file editing
272
uppy.on("dashboard:file-edit-start", (file) => {
273
console.log(`Started editing: ${file?.name}`);
274
// Show editing indicators, disable other actions, etc.
275
});
276
277
uppy.on("dashboard:file-edit-complete", (file) => {
278
console.log(`Finished editing: ${file?.name}`);
279
// Hide editing indicators, enable other actions, etc.
280
});
281
282
// Auto-save drafts during editing
283
let editingFile: UppyFile | null = null;
284
uppy.on("dashboard:file-edit-start", (file) => {
285
editingFile = file;
286
startAutoSave();
287
});
288
289
uppy.on("dashboard:file-edit-complete", () => {
290
editingFile = null;
291
stopAutoSave();
292
});
293
294
function startAutoSave() {
295
const interval = setInterval(() => {
296
if (editingFile) {
297
// Save current form state as draft
298
saveDraft(editingFile.id);
299
}
300
}, 30000); // Save every 30 seconds
301
}
302
```
303
304
### File Validation
305
306
Built-in file validation and restriction handling.
307
308
```typescript { .api }
309
/**
310
* File validation is handled by Uppy core
311
* Dashboard respects these restriction options:
312
*/
313
interface UppyRestrictions {
314
/** Allowed file types (MIME types or extensions) */
315
allowedFileTypes?: string[];
316
/** Maximum number of files */
317
maxNumberOfFiles?: number;
318
/** Maximum file size in bytes */
319
maxFileSize?: number;
320
/** Minimum file size in bytes */
321
minFileSize?: number;
322
/** Required metadata fields */
323
requiredMetaFields?: string[];
324
}
325
```
326
327
**Validation Examples:**
328
329
```typescript
330
// Configure file restrictions
331
const uppy = new Uppy({
332
restrictions: {
333
allowedFileTypes: ['.jpg', '.jpeg', '.png', '.gif'],
334
maxNumberOfFiles: 5,
335
maxFileSize: 10 * 1024 * 1024, // 10MB
336
requiredMetaFields: ['title', 'description']
337
}
338
});
339
340
// Handle validation errors
341
uppy.on('restriction-failed', (file, error) => {
342
console.error(`File ${file?.name} rejected:`, error.message);
343
// Show user-friendly error message
344
showErrorMessage(error.message);
345
});
346
347
// Custom validation
348
function validateFileContent(file: File): Promise<boolean> {
349
return new Promise((resolve) => {
350
const reader = new FileReader();
351
reader.onload = (e) => {
352
// Custom validation logic
353
const content = e.target?.result;
354
const isValid = performCustomValidation(content);
355
resolve(isValid);
356
};
357
reader.readAsArrayBuffer(file);
358
});
359
}
360
```
361
362
### File Processing
363
364
Integration with file processing and transformation.
365
366
```typescript { .api }
367
/**
368
* File processing integration points
369
*/
370
interface FileProcessing {
371
/** Generate thumbnails for files */
372
handleRequestThumbnail(file: UppyFile): void;
373
/** Cancel thumbnail generation */
374
handleCancelThumbnail(file: UppyFile): void;
375
/** Wait for thumbnails before upload */
376
waitForThumbnailsBeforeUpload?: boolean;
377
}
378
```
379
380
**Processing Examples:**
381
382
```typescript
383
// Configure thumbnail generation
384
uppy.use(Dashboard, {
385
thumbnailWidth: 300,
386
thumbnailHeight: 300,
387
thumbnailType: 'image/jpeg',
388
waitForThumbnailsBeforeUpload: true
389
});
390
391
// Custom file processing
392
uppy.on('file-added', async (file) => {
393
if (file.type?.startsWith('image/')) {
394
// Extract EXIF data
395
const exifData = await extractExifData(file.data);
396
uppy.setFileMeta(file.id, {
397
...file.meta,
398
exif: exifData,
399
location: exifData.gps
400
});
401
}
402
});
403
404
// Process files before upload
405
uppy.on('preprocess-progress', (file, progress) => {
406
console.log(`Processing ${file.name}: ${progress.uploadProgress}%`);
407
});
408
409
uppy.on('preprocess-complete', (file) => {
410
console.log(`Finished processing: ${file.name}`);
411
});
412
```
413
414
### Drag and Drop Integration
415
416
Built-in drag and drop functionality for file selection.
417
418
```typescript { .api }
419
/**
420
* Drag and drop event handlers
421
*/
422
interface DragDropHandlers {
423
/** Handle drag over events */
424
onDragOver?: (event: DragEvent) => void;
425
/** Handle drag leave events */
426
onDragLeave?: (event: DragEvent) => void;
427
/** Handle drop events */
428
onDrop?: (event: DragEvent) => void;
429
}
430
```
431
432
**Drag and Drop Examples:**
433
434
```typescript
435
// Custom drag and drop behavior
436
uppy.use(Dashboard, {
437
onDragOver: (event) => {
438
console.log('Files being dragged over dashboard');
439
// Add visual feedback
440
event.currentTarget.classList.add('drag-active');
441
},
442
443
onDragLeave: (event) => {
444
console.log('Drag left dashboard area');
445
// Remove visual feedback
446
event.currentTarget.classList.remove('drag-active');
447
},
448
449
onDrop: (event) => {
450
console.log('Files dropped on dashboard');
451
// Custom drop handling
452
const files = Array.from(event.dataTransfer?.files || []);
453
// Additional processing before adding files
454
files.forEach(file => preprocessFile(file));
455
}
456
});
457
458
// Drag and drop validation
459
function validateDropEvent(event: DragEvent): boolean {
460
const items = event.dataTransfer?.items;
461
if (!items) return false;
462
463
// Check if all items are files
464
for (let i = 0; i < items.length; i++) {
465
if (items[i].kind !== 'file') {
466
return false;
467
}
468
}
469
470
return true;
471
}
472
```