36 lines
1.5 KiB
TypeScript
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) };
|
|
}
|