feat: support parallel multi-file uploads

The browser upload flow was built around one selected file and one global
upload state. That made the existing chunk pool useful for a single file, but
users could not start several selected files at the same time.

Refactor the browser state into per-file upload items. Each selected file now
has its own upload record, completed-chunk set, abort controller, retry state,
progress row, and saved IndexedDB resume record. The picker accepts multiple
files, `Start all` and `Resume all` use a bounded file-level pool, and each file
keeps the existing bounded chunk pool. This keeps parallel uploads useful
without letting one large selection create unbounded request fan-out.

Keep the server API unchanged. Each file still receives a separate server upload
id, and server-side progress remains authoritative before any missing chunks are
scheduled. Terminal conflicts still stop the affected file without overwriting
completed data.

Update the user-facing markup, styles, project docs, and test checklist for the
multi-file scheduler. Add a server regression test that interleaves two uploads
and verifies the completed files contain exactly their own bytes.

Test Plan:
- just check
- git diff --check
This commit is contained in:
2026-05-30 18:32:29 +02:00
parent a7b3abd54a
commit 1923ff2a6f
8 changed files with 635 additions and 192 deletions
+8 -1
View File
@@ -24,7 +24,7 @@ upl
Browser UI
static/index.html upload tool markup
static/styles.css responsive tool styling
static/app.js upload scheduler, retries, and browser resume state
static/app.js multi-file scheduler, retries, and browser resume state
Deployment
deploy/nginx/ nginx reverse proxy example
scripts/ reusable local smoke tests
@@ -62,6 +62,13 @@ just run
`just check` also syntax-checks the static browser JavaScript with `node`.
## Browser Uploads
The browser UI accepts multiple selected files. `Start all` runs up to three
file uploads at the same time, and each file still uploads up to three chunks
concurrently. Every selected file keeps its own upload id, progress markers,
abort controller, retry state, and saved IndexedDB resume record.
## nginx
Run `upl` on localhost and put nginx in front of it for TLS and access control: