feat: B2 uit voor veilige archive-downloads
This commit is contained in:
+59
-3
@@ -460,6 +460,40 @@ function markZipDownloadFailed(err) {
|
||||
});
|
||||
}
|
||||
|
||||
function updateZipDownloadTaskProgress(task) {
|
||||
if (!downloadProgressState.active) {
|
||||
return;
|
||||
}
|
||||
updateDownloadModalDisplay({
|
||||
active: true,
|
||||
targetText: "Preparing download...",
|
||||
currentFileText: task.current_item ? `Current: ${task.current_item}` : `Selection: ${selectedItemCountLabel(downloadProgressState.totalItems)}`,
|
||||
countText: task.total_items ? `${task.done_items || 0}/${task.total_items} top-level items` : "Preparing zip download",
|
||||
statusText: task.status === "ready" ? "Download started" : "Preparing download...",
|
||||
percent: task.status === "ready" ? 100 : 55,
|
||||
});
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise((resolve) => window.setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function waitForArchiveDownloadReady(taskId) {
|
||||
while (true) {
|
||||
const task = await getTaskRequest(taskId);
|
||||
if (task.status === "ready") {
|
||||
return task;
|
||||
}
|
||||
if (task.status === "failed") {
|
||||
const err = new Error(task.error_message || "Archive download failed");
|
||||
err.code = task.error_code || null;
|
||||
throw err;
|
||||
}
|
||||
updateZipDownloadTaskProgress(task);
|
||||
await sleep(250);
|
||||
}
|
||||
}
|
||||
|
||||
function closeDownloadModal() {
|
||||
if (downloadProgressState.active) {
|
||||
return;
|
||||
@@ -643,15 +677,20 @@ async function startDownloadSelected() {
|
||||
}
|
||||
try {
|
||||
const selected = selectedItems[0];
|
||||
if (zipDownload) {
|
||||
const created = await createArchiveDownloadTask(selectedPaths);
|
||||
const task = await waitForArchiveDownloadReady(created.task_id);
|
||||
startArchiveDownload(task.id, task.destination);
|
||||
markZipDownloadReady(task.destination);
|
||||
setStatus(`Download started: ${task.destination}`);
|
||||
return;
|
||||
}
|
||||
const { blob, fileName } = await downloadFileRequest(selectedPaths);
|
||||
const url = URL.createObjectURL(blob);
|
||||
const anchor = document.createElement("a");
|
||||
anchor.href = url;
|
||||
anchor.download = fileName || selected.name;
|
||||
document.body.append(anchor);
|
||||
if (zipDownload) {
|
||||
markZipDownloadReady(anchor.download);
|
||||
}
|
||||
anchor.click();
|
||||
anchor.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
@@ -957,6 +996,23 @@ async function downloadFileRequest(paths) {
|
||||
};
|
||||
}
|
||||
|
||||
async function createArchiveDownloadTask(paths) {
|
||||
return apiRequest("POST", "/api/files/download/archive-prepare", { paths });
|
||||
}
|
||||
|
||||
async function getTaskRequest(taskId) {
|
||||
return apiRequest("GET", `/api/tasks/${encodeURIComponent(taskId)}`);
|
||||
}
|
||||
|
||||
function startArchiveDownload(taskId, fileName) {
|
||||
const anchor = document.createElement("a");
|
||||
anchor.href = `/api/files/download/archive/${encodeURIComponent(taskId)}`;
|
||||
anchor.download = fileName || "";
|
||||
document.body.append(anchor);
|
||||
anchor.click();
|
||||
anchor.remove();
|
||||
}
|
||||
|
||||
async function uploadFileRequest(targetPath, file, overwrite = false) {
|
||||
const formData = new FormData();
|
||||
formData.append("target_path", targetPath);
|
||||
|
||||
Reference in New Issue
Block a user