feat(files): streaming ZIP download in the project explorer
Nightly Build / build (push) Successful in 8m52s
Nightly Build / build (push) Successful in 8m52s
Each row of the project Files tab gains a download action, and the toolbar gains a Download ZIP button scoped to the folder being browsed (at the root, the whole project). Visible to read-only members too: download is a read. Single files need no new backend: they reuse GET /api/file?force_download. Directories go through the new GET /api/file/download, which builds the ZIP on the fly: an async task walks the tree and async_zip (Astral's maintained rs-async-zip fork) streams entries into a bounded duplex stream backing the response body — no temp file, no whole-archive buffer, backpressure for free, and the task dies with the client. Compression is per entry: Deflate at maximum level, except files whose magic bytes name an already-compressed format (media/PDF via the shared sniffer, the ZIP family, gzip/zstd/7z/rar, compressed audio), which are Stored. Entries are prefixed with the folder name, empty folders and unix permission bits survive, symlinks are never followed into the archive, and containment stays fail-closed under the resolved root. Covered by a round-trip test read back with the crate's own reader (and verified against unzip/python's zipfile).
This commit is contained in:
@@ -55,6 +55,8 @@ If you have write access you can also, from the toolbar or each row:
|
||||
|
||||
Read-only members see the same explorer and can open every file, but the write actions are hidden (and refused by the server anyway).
|
||||
|
||||
**Downloading.** Every member can download what they see: each row has a download icon, and the toolbar has a **Download ZIP** button that always applies to the folder you are currently browsing (at the project root, that's the whole project). A single file downloads as-is; a folder downloads as a ZIP archive, built on the fly on the server. Inside the archive the folder keeps its name, and files that are already compressed (photos, videos, PDFs, other archives) are stored as-is so the download stays fast.
|
||||
|
||||
## The Sharing tab
|
||||
|
||||
Lists every member with their access level. The owner and any read & write member can:
|
||||
|
||||
Reference in New Issue
Block a user