Skip to content

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 onProgress callback
  • Abort controller for cancellation
  • Error handling with user feedback
  • Emits download-file event 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-folder event 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-file event on completion
  • Error handling with user feedback

setDownloadingItem(id, item) ​

Set or update a downloading item in state.

Parameters:

  • id: string - Download item ID
  • item: 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 panel

expanded ​

Download panel expanded state.

typescript
const downloadStore = useDownloadStore()
downloadStore.expanded = false // Collapse download panel

count ​

Number of active downloads.

typescript
const downloadStore = useDownloadStore()
const activeDownloads = downloadStore.count

files ​

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