Add chunked, resumable uploads

Split each uploaded file into 5 MB chunks posted sequentially to a new
/api/upload/chunk endpoint, then assemble them on the server via
/api/upload/finalize. The client queries /api/upload/chunk/:uploadId/:fileIndex
to skip chunks already received, so an interrupted upload resumes instead
of restarting. Each chunk is retried with backoff. Path components are
sanitized and the same canUpload/library-access checks as /api/upload are
enforced. The legacy /api/upload endpoint is left intact.

The chunk staging directory defaults to <metadata>/uploads and can be
relocated with UPLOAD_TEMP_DIR so large in-progress uploads can be staged
off the metadata volume.
This commit is contained in:
Boris Rybalkin 2026-06-10 22:06:38 +01:00
parent cbda0360aa
commit 669e0255a9
4 changed files with 410 additions and 22 deletions

View file

@ -339,6 +339,9 @@ class ApiRouter {
// Misc Routes
//
this.router.post('/upload', MiscController.handleUpload.bind(this))
this.router.post('/upload/chunk', MiscController.handleUploadChunk.bind(this))
this.router.get('/upload/chunk/:uploadId/:fileIndex', MiscController.getUploadChunks.bind(this))
this.router.post('/upload/finalize', MiscController.handleUploadFinalize.bind(this))
this.router.get('/tasks', MiscController.getTasks.bind(this))
this.router.patch('/settings', MiscController.updateServerSettings.bind(this))
this.router.patch('/sorting-prefixes', MiscController.updateSortingPrefixes.bind(this))