Appearance
Download Store ​
File Information ​
- Path:
app/stores/download.ts - Store Name:
download - Purpose: Download state management with progress tracking
- Type: Pinia Store (Composition API)
Overview ​
The Download Store manages file downloads with progress tracking, cancellation support, and multiple download methods. It handles single file downloads, multiple file downloads (as ZIP), and image asset downloads with proper progress tracking and error handling.
State ​
typescript
{
pinned: boolean, // Download panel pinned state
expanded: boolean, // Download panel expanded state
count: number, // Number of active downloads
files: Record<string, DownloadItem> // Active download items by ID
}DownloadItem ​
typescript
{
url: string, // Download URL
name: string, // File name
progress: number, // Download progress (0-100)
loaded: number, // Bytes loaded
total: number, // Total bytes
downloading: boolean, // Download in progress
errorMessage?: string, // Error message if failed
source?: AbortController, // Abort controller for cancellation
// ... other properties from extras
}Actions ​
downloadFile(payload) ​
Download a single file with progress tracking.
Parameters:
typescript
{
id: string, // Unique download ID
url: string, // File download URL
name: string, // File name
file_type?: string, // File type/extension
collection_id?: string, // Collection ID (optional)
callCountApi?: boolean, // Call count API (default: true)
useModernDownload?: boolean, // Use modern download (default: false)
extras?: Record<string, any>, // Additional properties
multiple?: boolean // Multiple files flag
}Returns: Promise<DownloadItem>
Usage:
typescript
const downloadStore = useDownloadStore()
await downloadStore.downloadFile({
id: 'file-123',
url: '/api/files/download/123',
name: 'document.pdf',
file_type: 'pdf',
callCountApi: true
})Features:
- Progress tracking via
onProgresscallback - Abort controller for cancellation
- Error handling with user feedback
- Emits
download-fileevent on completion/error - Prevents duplicate downloads
downloadMultipleFiles(payload) ​
Download multiple files as a ZIP archive.
Parameters:
typescript
{
files?: any[], // Array of file IDs
folders?: string[], // Array of folder IDs
collection_id?: string, // Collection ID
share_id?: string, // Share ID
download_name?: string, // ZIP file name
shareWorkspaceId?: string, // Share workspace ID
shareMode?: boolean // Share mode flag
}Returns: Promise<{ status: string, message?: string, filename?: string }>
Status Values:
"email-notification"- Large download, email sent"success-direct-link"- Direct download link"success"- Stream download successful"error"- Download failed
Usage:
typescript
const downloadStore = useDownloadStore()
// Download multiple files
const result = await downloadStore.downloadMultipleFiles({
files: ['file-1', 'file-2', 'file-3'],
download_name: 'my-files.zip'
})
if (result.status === 'email-notification') {
// Email will be sent
} else if (result.status === 'success') {
// Download successful
}Features:
- Handles large downloads via email notification
- Direct link downloads for smaller files
- Stream-based downloads using StreamSaver
- Progress tracking for stream downloads
- Emits
download-all-folderevent on completion
downloadImageAsset(payload) ​
Download a generated image asset with proper MIME type.
Parameters:
typescript
{
assetId: string, // Asset ID
fileName: string, // File name
fileType: string // File type (jpg, png, webp, etc.)
}Returns: Promise<void>
Usage:
typescript
const downloadStore = useDownloadStore()
await downloadStore.downloadImageAsset({
assetId: '123',
fileName: 'image.jpg',
fileType: 'jpg'
})Features:
- Proper MIME type handling
- Supports multiple image formats (apng, avif, gif, png, webp, jpg)
- Emits
download-fileevent on completion - Error handling with user feedback
setDownloadingItem(id, item) ​
Set or update a downloading item in state.
Parameters:
id: string- Download item IDitem: Partial<DownloadItem>- Item properties to update
Returns: void
Usage:
typescript
const downloadStore = useDownloadStore()
downloadStore.setDownloadingItem('file-123', {
progress: 50,
loaded: 1024,
total: 2048
})Note: This is a mutation helper for backward compatibility. Updates download count automatically.
State Properties ​
pinned ​
Download panel pinned state.
typescript
const downloadStore = useDownloadStore()
downloadStore.pinned = true // Pin download panelexpanded ​
Download panel expanded state.
typescript
const downloadStore = useDownloadStore()
downloadStore.expanded = false // Collapse download panelcount ​
Number of active downloads.
typescript
const downloadStore = useDownloadStore()
const activeDownloads = downloadStore.countfiles ​
Record of all active download items.
typescript
const downloadStore = useDownloadStore()
const downloadItem = downloadStore.files['file-123']Usage Examples ​
Single File Download ​
typescript
import { useDownloadStore } from '~/stores/download'
const downloadStore = useDownloadStore()
// Download single file
await downloadStore.downloadFile({
id: 'asset-123',
url: '/api/assets/123/download',
name: 'document.pdf',
file_type: 'pdf'
})
// Check progress
watch(() => downloadStore.files['asset-123'], (item) => {
if (item) {
console.log(`Progress: ${item.progress}%`)
console.log(`Loaded: ${item.loaded} / ${item.total} bytes`)
}
})Multiple Files Download ​
typescript
const downloadStore = useDownloadStore()
// Download multiple files as ZIP
const result = await downloadStore.downloadMultipleFiles({
files: ['file-1', 'file-2', 'file-3'],
folders: ['folder-1'],
download_name: 'my-download.zip'
})
if (result.status === 'email-notification') {
snackbar.showSuccess('You will receive an email with download link!')
} else if (result.status === 'success') {
snackbar.showSuccess(`Downloaded: ${result.filename}`)
}Image Asset Download ​
typescript
const downloadStore = useDownloadStore()
// Download image asset
await downloadStore.downloadImageAsset({
assetId: '123',
fileName: 'image.jpg',
fileType: 'jpg'
})Track Download Progress ​
typescript
const downloadStore = useDownloadStore()
// Listen to download events
const { $mittBus } = useNuxtApp()
$mittBus.on('download-file', (fileId) => {
const item = downloadStore.files[fileId]
if (item && !item.downloading) {
if (item.errorMessage) {
console.error('Download failed:', item.errorMessage)
} else {
console.log('Download completed:', item.name)
}
}
})
$mittBus.on('download-all-folder', () => {
console.log('Bulk download completed')
})Event Emissions ​
The store emits events via $mittBus:
download-file ​
Emitted when a single file download completes or fails.
Event Data: fileId: string
download-all-folder ​
Emitted when a bulk download (multiple files) completes or fails.
Error Handling ​
- AbortError: Download was cancelled
- Network Errors: Displayed via snackbar
- API Errors: Error message from API response
- Stream Errors: Handled gracefully with user feedback
Dependencies ​
- FileSaver - For saving files to disk
- StreamSaver - For large file stream downloads
- useDownloadApi - Download API composable
- useSnackbar - Notification system
- useHelpers - Helper functions
Notes for Development ​
- Uses Composition API (setup function)
- State is reactive using
reactive() - Exposed via
toRefs()for destructuring - Progress tracking via callbacks
- Abort controllers for cancellation
- Stream-based downloads for large files
- Email notification for very large downloads
- Proper MIME type handling for images
- Event emissions for UI updates
Related Documentation ​
- Download API - Download API endpoints
- useDownloadApi Composable - Download API composable
- Stream Saver Plugin - Stream-based downloads
- Mitt Plugin - Event bus