File Uploads
Learn how to handle file inputs and uploads in Aurelia forms.
Basic File Input
<form>
<label for="fileUpload">Select files to upload:</label>
<input
id="fileUpload"
type="file"
multiple
accept="image/*"
change.trigger="handleFileSelect($event)" />
<button
click.trigger="uploadFiles()"
disabled.bind="!selectedFiles.length">
Upload
</button>
</form>export class FileUploadComponent {
selectedFiles: File[] = [];
handleFileSelect(event: Event) {
const input = event.target as HTMLInputElement;
if (!input.files?.length) return;
this.selectedFiles = Array.from(input.files);
}
async uploadFiles() {
if (this.selectedFiles.length === 0) return;
const formData = new FormData();
for (const file of this.selectedFiles) {
formData.append('files', file, file.name);
}
try {
const response = await fetch('/api/upload', {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`Upload failed with status ${response.status}`);
}
const result = await response.json();
console.log('Upload successful:', result);
this.selectedFiles = [];
} catch (error) {
console.error('Error uploading files:', error);
}
}
}Single File Upload
<input type="file" accept="image/*" change.trigger="handleFileSelect($event)" />handleFileSelect(event: Event) {
const input = event.target as HTMLInputElement;
this.selectedFiles = input.files?.length ? [input.files[0]] : [];
}File Preview
export class FilePreviewComponent {
selectedFile: File | null = null;
previewUrl: string | null = null;
handleFileSelect(event: Event) {
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
if (file) {
this.selectedFile = file;
this.createPreview(file);
}
}
private createPreview(file: File) {
if (this.previewUrl) {
URL.revokeObjectURL(this.previewUrl);
}
this.previewUrl = URL.createObjectURL(file);
}
detaching() {
if (this.previewUrl) {
URL.revokeObjectURL(this.previewUrl);
}
}
}<input type="file" accept="image/*" change.trigger="handleFileSelect($event)" />
<div if.bind="previewUrl" class="preview">
<img src.bind="previewUrl" alt="Preview" />
<p>${selectedFile.name} (${(selectedFile.size / 1024).toFixed(2)} KB)</p>
</div>Validation
export class ValidatedFileUpload {
selectedFile: File | null = null;
error: string | null = null;
maxSize = 5 * 1024 * 1024; // 5MB
allowedTypes = ['image/jpeg', 'image/png', 'image/gif'];
handleFileSelect(event: Event) {
this.error = null;
const input = event.target as HTMLInputElement;
const file = input.files?.[0];
if (!file) return;
if (!this.allowedTypes.includes(file.type)) {
this.error = 'Only JPEG, PNG, and GIF images are allowed';
input.value = '';
return;
}
if (file.size > this.maxSize) {
this.error = `File size must be less than ${this.maxSize / (1024 * 1024)}MB`;
input.value = '';
return;
}
this.selectedFile = file;
}
}Progress Tracking
export class FileUploadWithProgress {
uploadProgress = 0;
isUploading = false;
async uploadWithProgress(file: File) {
this.isUploading = true;
this.uploadProgress = 0;
const xhr = new XMLHttpRequest();
return new Promise((resolve, reject) => {
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
this.uploadProgress = (e.loaded / e.total) * 100;
}
});
xhr.addEventListener('load', () => {
this.isUploading = false;
if (xhr.status >= 200 && xhr.status < 300) {
resolve(JSON.parse(xhr.responseText));
} else {
reject(new Error(`Upload failed: ${xhr.status}`));
}
});
xhr.addEventListener('error', () => {
this.isUploading = false;
reject(new Error('Upload failed'));
});
const formData = new FormData();
formData.append('file', file);
xhr.open('POST', '/api/upload');
xhr.send(formData);
});
}
}<input type="file" change.trigger="handleFileSelect($event)" />
<div if.bind="isUploading" class="progress">
<div class="progress-bar" css="width: ${uploadProgress}%"></div>
<span>${uploadProgress.toFixed(0)}%</span>
</div>Best Practices
Validate on both client and server - Always verify file types and sizes server-side
Clean up object URLs - Revoke object URLs in
detaching()to prevent memory leaksShow progress for large files - Use XMLHttpRequest for progress tracking
Provide clear feedback - Show file names, sizes, and upload status
Handle errors gracefully - Display meaningful error messages
Security Considerations
Validate file types server-side (don't trust
acceptattribute)Check file sizes to prevent DoS attacks
Scan uploaded files for malware
Store files outside web root
Use unique filenames to prevent overwrites
Implement rate limiting
Related
Last updated
Was this helpful?