36 lines
1.5 KiB
TypeScript

/** Downloads through the authenticated canvas export route, including cross-origin media. */
export async function downloadCanvasMedia(files: Array<{ url: string; name: string }>) {
if (!files.length) throw Error("没有可下载的素材");
if (files.length > 200) throw Error("每次最多下载 200 项,请分批选择");
const batch = files.length > 1;
const response = await fetch(batch ? "/api/canvas/download-zip" : "/api/canvas/download-image", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(batch ? { files, folderName: "画布素材" } : files[0]),
signal: AbortSignal.timeout(300000),
});
if (!response.ok) {
const data = await response.json().catch(() => ({}));
throw Error(data.error || "素材下载失败");
}
const blob = await response.blob();
if (!blob.size) throw Error("返回的下载文件为空");
const encodedName = response.headers
.get("content-disposition")
?.match(/filename\*=UTF-8''([^;]+)/i)?.[1];
const filename = encodedName
? decodeURIComponent(encodedName)
: batch
? "画布素材.zip"
: files[0].name;
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.href = url;
link.download = filename;
document.body.appendChild(link);
link.click();
link.remove();
window.setTimeout(() => URL.revokeObjectURL(url), 60000);
return { failed: Number(response.headers.get("X-Download-Failed-Count") || 0) };
}