SwUploadFile
SwUploadFile is a chunked upload component for plain files (PDF / documents / zip — anything
that isn't an image or video), supporting both click-to-select and drag-and-drop. It is the
unstyled UI shell over the useUploader().uploadFile
capability: it reuses the same chunked endpoint as SwUploadVideo, but without the transcoding
step (no queryFn needed) — the chunk-success response already carries an accessible URL, so
uploadFn resolves the result directly.
Use
SwUploadImagefor images,SwUploadVideofor videos, and this component for everything else. All three are unstyled: they render no UI of their own, inject upload logic viauploadFn, and expose state through the default slot.
Basic Usage + Progress
Click to select a file; the progress scope variable and progress event reflect chunked upload
progress in real time.
Basic (click upload + progress)
<script setup lang="ts">
const uploader = useUploader()
function onDone(result: { id: string; value: string }) {
form.attachment = { id: result.id, url: result.value }
}
</script>
<template>
<SwUploadFile :upload-fn="uploader.uploadFile" @success="onDone" v-slot="{ open, pending, progress }">
<SwButton :disabled="pending" @click="open">
{{ pending ? `Uploading ${progress}%` : 'Select File' }}
</SwButton>
</SwUploadFile>
</template>
Custom trigger area (#default slot)
The "+ upload card": the default slot fully takes over the trigger UI; a clickable download link appears when done.
+ upload card (slot customization + download link)
Drag and Drop
Use the slot's isOver to highlight the drop zone. Plain files are not mime-restricted — any file
can be dropped.
Drag + click dual channel
Restrict file types (accept)
accept is passed through to the file picker, filtering at the selection level.
PDF / zip only
Multiple Files
Enable multiple to select or drop several files at once; they upload concurrently and emit
success one by one.
Multiple files
Progress trade-off:
progressis accurate for single-file uploads; withmultiple, per-file progress interleaves (last writer wins), so the progress bar is primarily meaningful for the single-file case.
Props
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
uploadFn | (file: File, options?: FileUploadOptions) => Promise<FileUploadResult> | ✓ | — | Actual upload function, usually useUploader().uploadFile |
accept | string | '*' | File picker accept (plain files unrestricted by default) | |
chunkSize | number | 2097152 (2 MB) | Chunk size in bytes, forwarded to uploadFn | |
retries | number | 3 | Max retries per chunk, forwarded to uploadFn | |
concurrency | number | undefined | Concurrent chunks; defaults to 6 underneath, forwarded to uploadFn | |
multiple | boolean | false | Whether to allow multiple files |
Type Definitions
FileUploadOptions
interface FileUploadOptions {
chunkSize?: number
retries?: number
concurrency?: number
onProcess?: (result: ChunkProgress) => void
onBefore?: (file: File) => void
}
FileUploadResult
type FileUploadResult = {
id: string // Backend file ID (business-side foreign key)
value: string // File access URL (same `value` semantics as uploadImage)
file_md5: string // Whole-file MD5
}
Events
| Event | Payload | Description |
|---|---|---|
progress | pct: number | Upload progress percentage (0–100) |
success | FileUploadResult | Fires when a single file uploads successfully (one per file) |
error | err: Error | Fires on upload error (non-Error normalized to Error) |
Slots
default (scoped slot)
| Scope variable | Type | Description |
|---|---|---|
isOver | boolean | A file is hovering over the zone |
pending | boolean | Upload in progress |
progress | number | Current upload progress (0–100) |
open | () => void | Manually open the file dialog |
Notes
- Unstyled: no built-in CSS; the UI is entirely up to the slot consumer.
uploadFnis usually wrapped fromuseUploader(theuploadFilemethod); demos use a mock to illustrate the flow.- No transcoding step: the key difference from
SwUploadVideo— plain files yieldvalue(URL) immediately after upload, with noqueryFnpolling. - Repeated triggers during
pendingare ignored (prevents duplicate uploads); the UI should reflectpendingwith a disabled / loading state.