createUploader
An upload-tool factory compatible with the legacy backend's upload endpoints. Returns four methods — { uploadImage, uploadVideo, uploadFile, queryVideo } — covering single-shot image upload, concurrent chunked video upload with transcode polling, and generic file (PDF / docs / zip) chunked upload.
📌 Business code should prefer the
useUploadercomposable or theSwUploadImage/SwUploadVideo/SwUploadFilecomponents — a framework plugin already instantiatescreateUploaderwith systemInfo / userId wired up. CallingcreateUploaderdirectly is mainly for custom-injection scenarios (e.g. non-standard store sources).
How It Works
- The factory takes system config and userId as getters (
getSystemInfo/getUserId), evaluated at call time to avoid stale closures. uploadImage: validates the byte size locally first (images useupload_image_max_length, falling back toupload_file_max_lengthwhen unset); single POST whose responsefile_info(e.g."1280x720") is parsed into width / height.uploadVideo: each File gets its own chunk uploader instance, running concurrently without blocking each other; defaults to 2MB chunks and 3 retries per chunk.uploadFile: shares the chunk endpoint with video but has no transcode phase (never callsqueryVideo) — the final chunk response already contains the accessible URL, returned as a Promise.queryVideo: polls the transcode result every 3 seconds untilfile_m3u8is available or retries are exhausted (default 20 ≈ 60 seconds).
Endpoint URLs (upload_image_url etc.) come from systemInfo with common params already attached; upload timeout follows uploadTimeout in the request block of swift.config.json (default 600s).
API
const uploader = createUploader({
getSystemInfo: () => useSystemStore().info as SystemInfo,
getUserId: () => useUserStore().id,
})
| Method | Signature | Notes |
|---|---|---|
uploadImage | (file: File, thumbnail: boolean) => Promise<{ id, value, width, height }> | Single-shot image upload; thumbnail requests a thumbnail; value is the file URL |
uploadVideo | (files: File[], options?) => void | Concurrent chunked video upload; results via onProcess / onSuccess / onError callbacks |
uploadFile | (file: File, options?) => Promise<{ id, value, file_md5 }> | Chunked generic-file upload, no transcoding; value is the access URL |
queryVideo | (id: string, retries = 20) => Promise<VideoQueryResult> | Polls transcode result; returns { id, file_m3u8, file_duration, file_preview_m3u8, file_status, width, height } |
Options for uploadVideo / uploadFile: chunkSize (default 2MB) / retries (default 3) / onProcess (progress { processed_num, chunk_total }) / onBefore; uploadVideo additionally takes onSuccess / onError, uploadFile additionally takes concurrency (concurrent chunks, default 6).
Examples
// Upload an image and fill the form
const { id, value, width, height } = await uploader.uploadImage(file, false)
form.cover = { id, url: value, w: width, h: height }
// Chunked video upload + progress + transcode query
uploader.uploadVideo([videoFile], {
onProcess: ({ processed_num, chunk_total }) => (progress.value = processed_num / chunk_total),
onSuccess: async ({ id }) => {
form.video = await uploader.queryVideo(id)
},
onError: (e) => console.error('upload failed', e),
})
// Generic file (Promise style, no transcode phase)
const { value: fileUrl } = await uploader.uploadFile(pdfFile, {
onProcess: ({ processed_num, chunk_total }) => (progress.value = processed_num / chunk_total),
})
Caveats
queryVideo throws after ~60 seconds by default (UUP-001, warning)
Default polling is 20 attempts × 3s, then it throws Error('查询重试次数已用尽'). With a slow / broken transcoder the flow stalls for 60s and then throws — always try/catch with UI feedback, or raise the retry count:
onSuccess: async ({ id }) => {
try {
form.video = await uploader.queryVideo(id)
} catch {
useToast().info('Video still processing — check your drafts later') // or queryVideo(id, 40)
}
}
Others
- Browser only (depends on File / FormData / Blob) — never call during SSR.
uploadImagethrowsError('文件超出大小')when exceedingupload_file_max_length; failedfile_info/file_qualitydimension parsing also throws explicit errors.uploadVideosilently retries each failed chunk untilretriesis exhausted, only then invokingonError.