File Upload
Upload files to Dropper with progress tracking, metadata, and folder organization.
Basic Upload
Upload a single file:
import { DropperClient } from '@dropper/core'
const client = new DropperClient({
publishableKey: 'pk_dropper_test_xxx',
})
const file = new File(['content'], 'example.txt')
const result = await client.uploadFile(file)
console.log('Uploaded:', result.url)
Upload with Progress
Track upload progress with a callback:
const result = await client.uploadFile(file, {
onProgress: (progress) => {
console.log(`Upload progress: ${progress}%`)
// Update UI progress bar
updateProgressBar(progress)
},
})
Upload Options
UploadOptions Interface
interface UploadOptions {
folderId?: string // Upload to specific folder
metadata?: Record<string, unknown> // Custom metadata
onProgress?: (progress: number) => void // Progress callback (0-100)
signal?: AbortSignal // Abort controller signal
}
Upload to Folder
Organize files by uploading to a specific folder:
const result = await client.uploadFile(file, {
folderId: 'folder_abc123',
})
Add Custom Metadata
Attach custom metadata to files:
const result = await client.uploadFile(file, {
metadata: {
userId: '123',
category: 'profile-pictures',
tags: ['avatar', 'user'],
},
})
Upload Process
Dropper uses a 3-step upload process for optimal performance:
Step 1: Get Signed URL
The client requests a signed upload URL from the Dropper API:
// Internal: Client sends file metadata
POST /files/sdk/upload-url
{
"filename": "photo.jpg",
"mimeType": "image/jpeg",
"size": 1024000,
"folderId": "folder_123",
"metadata": { "userId": "123" }
}
// Response: Signed URL for direct upload
{
"fileId": "file_abc123",
"uploadUrl": "https://storage.provider.com/...",
"uploadMethod": "PUT",
"fileKey": "uploads/file_abc123"
}
Step 2: Direct Upload
The file is uploaded directly to the storage provider (S3, Azure, etc.):
// Internal: Direct PUT to storage provider
PUT https://storage.provider.com/...
Content-Type: image/jpeg
Body: [file binary data]
This direct upload:
- Bypasses your server
- Reduces bandwidth costs
- Improves upload speed
- Provides progress tracking
Step 3: Confirm Upload
The client confirms the upload completion:
// Internal: Confirm upload
POST /files/sdk/{fileId}/confirm
{
"metadata": { "userId": "123" }
}
// Response: Complete file record
{
"id": "file_abc123",
"originalFilename": "photo.jpg",
"url": "https://cdn.dropper.com/...",
...
}
Cancel Upload
Cancel an in-progress upload using AbortController:
const abortController = new AbortController()
// Start upload
const uploadPromise = client.uploadFile(file, {
signal: abortController.signal,
onProgress: (progress) => console.log(`${progress}%`),
})
// Cancel after 2 seconds
setTimeout(() => {
abortController.abort()
console.log('Upload cancelled')
}, 2000)
try {
await uploadPromise
} catch (error) {
console.error('Upload cancelled or failed:', error)
}
File Response
After successful upload, you receive a FileResponseDto:
interface FileResponseDto {
id: string // Unique file ID
originalFilename: string // Original filename
mimeType: string // MIME type (e.g., "image/jpeg")
size: number // File size in bytes
storagePath: string // Storage path
isPublic: boolean // Public access flag
extension?: string // File extension (e.g., "jpg")
virtualPath?: string // Virtual path
width?: number // Image width (if image)
height?: number // Image height (if image)
duration?: number // Video duration (if video)
url: string // Public URL
thumbnailUrl?: string // Thumbnail URL (if image/video)
folderId?: string // Parent folder ID
appId: string // App ID
metadata?: Record<string, unknown> // Custom metadata
createdAt: string // ISO timestamp
updatedAt: string // ISO timestamp
}
Complete Example
import { DropperClient } from '@dropper/core'
const client = new DropperClient({
publishableKey: process.env.DROPPER_KEY!,
})
async function uploadWithProgress(file: File) {
const abortController = new AbortController()
try {
const result = await client.uploadFile(file, {
folderId: 'folder_123',
metadata: {
uploadedBy: 'user_456',
category: 'documents',
},
onProgress: (progress) => {
console.log(`Uploading ${file.name}: ${progress}%`)
// Update UI
updateProgressBar(progress)
// Cancel if user clicks cancel button
if (shouldCancel()) {
abortController.abort()
}
},
signal: abortController.signal,
})
console.log('Upload successful!')
console.log('File URL:', result.url)
console.log('File ID:', result.id)
console.log('File size:', result.size, 'bytes')
// Image-specific info
if (result.width && result.height) {
console.log(`Dimensions: ${result.width}x${result.height}`)
}
return result
} catch (error) {
if (error.name === 'AbortError') {
console.log('Upload cancelled by user')
} else {
console.error('Upload failed:', error)
}
throw error
}
}
Error Handling
Handle upload errors gracefully:
try {
const result = await client.uploadFile(file)
} catch (error) {
if (error.statusCode === 401) {
console.error('Invalid API key')
} else if (error.statusCode === 413) {
console.error('File too large')
} else if (error.statusCode === 415) {
console.error('File type not supported')
} else {
console.error('Upload failed:', error.message)
}
}
Best Practices
1. Validate Before Upload
Validate files before uploading to provide immediate feedback:
import { validateFiles } from '@dropper/core'
const errors = validateFiles([file], {
accept: 'image/*',
maxSize: 5 * 1024 * 1024, // 5MB
})
if (errors.length > 0) {
console.error('Validation failed:', errors[0].message)
return
}
// Proceed with upload
const result = await client.uploadFile(file)
2. Show Progress Feedback
Always show upload progress to users:
const result = await client.uploadFile(file, {
onProgress: (progress) => {
// Update progress bar
progressBar.style.width = `${progress}%`
progressText.textContent = `${progress}%`
},
})
3. Handle Errors
Provide clear error messages:
try {
const result = await client.uploadFile(file)
showSuccess('File uploaded successfully!')
} catch (error) {
showError(`Upload failed: ${error.message}`)
}
4. Use Metadata
Add metadata for better file organization:
const result = await client.uploadFile(file, {
metadata: {
userId: currentUser.id,
uploadDate: new Date().toISOString(),
source: 'web-app',
},
})
Next Steps
- Upload Queue - Upload multiple files concurrently
- File Management - List and manage uploaded files
- Validation - Validate files before upload