fix: implement streaming downloads for large files
Run Tests / Backend Tests (pull_request) Failing after 5m29s
Run Tests / Frontend Tests (pull_request) Failing after 3m55s
Run Tests / Test Summary (pull_request) Failing after 18s

- Add token-based download system with 5-minute expiry
- Stream files in 8MB chunks on backend (no memory loading)
- Use browser native download with tokens on frontend
- Fixes hang on large files (10GB+) by avoiding memory buffering
This commit is contained in:
Gan, Jimmy
2026-04-18 11:03:22 +08:00
parent 45a7ce3ece
commit 88e53f3f8e
2 changed files with 75 additions and 15 deletions
+12 -10
View File
@@ -203,25 +203,27 @@ export async function download(path, filename) {
if (token) headers["Authorization"] = `Bearer ${token}`;
try {
const r = await fetch(`${BASE}/files/download?path=${encodeURIComponent(path)}`, {
method: "GET",
// Get a temporary download token
const tokenResponse = await fetch(`${BASE}/files/download-token?path=${encodeURIComponent(path)}`, {
method: "POST",
headers,
});
if (!r.ok) {
const errorText = await r.text();
console.error(`Download failed: ${r.status} - ${errorText}`);
throw new Error(`Download failed: ${r.status}`);
if (!tokenResponse.ok) {
const errorText = await tokenResponse.text();
console.error(`Download token failed: ${tokenResponse.status} - ${errorText}`);
throw new Error(`Download failed: ${tokenResponse.status}`);
}
const blob = await r.blob();
const url = window.URL.createObjectURL(blob);
const { token: downloadToken } = await tokenResponse.json();
// Use the token to trigger browser download (no memory loading)
const downloadUrl = `${BASE}/files/download?token=${downloadToken}`;
const a = document.createElement("a");
a.href = url;
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
} catch (e) {
console.error("Download error:", e);