fix: switch canvas zip download to native form submission
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-02-19 22:10:31 +08:00
parent e344a6db73
commit 056514f167
2 changed files with 36 additions and 53 deletions

View File

@ -103,7 +103,21 @@ export async function POST(request: NextRequest) {
return NextResponse.json({ success: false, error: "未登录" }, { status: 401 });
}
const body = await request.json().catch(() => ({}));
let body: Record<string, unknown> = {};
const contentType = request.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
body = (await request.json().catch(() => ({}))) as Record<string, unknown>;
} else {
const formData = await request.formData().catch(() => null);
const payload = formData?.get("payload");
if (typeof payload === "string" && payload.trim()) {
try {
body = (JSON.parse(payload) as Record<string, unknown>) || {};
} catch (_error) {
body = {};
}
}
}
const requestOrigin = getRequestOrigin(request);
const files = toDownloadItems((body as any)?.files, requestOrigin);
const folderName = sanitizeFolderName(String((body as any)?.folderName || ""));

View File

@ -36,18 +36,6 @@ function isNodeInViewport(
);
}
function downloadBlob(blob: Blob, filename: string): void {
const link = document.createElement("a");
const objectUrl = URL.createObjectURL(blob);
link.href = objectUrl;
link.download = filename;
link.rel = "noopener noreferrer";
document.body.appendChild(link);
link.click();
link.remove();
window.setTimeout(() => URL.revokeObjectURL(objectUrl), 1500);
}
export function CanvasWorkspace() {
const containerRef = useRef<HTMLDivElement>(null);
const [isPanning, setIsPanning] = useState(false);
@ -563,51 +551,32 @@ export function CanvasWorkspace() {
}
setIsDownloadSubmitting(true);
let timeoutId: number | null = null;
try {
const controller = new AbortController();
timeoutId = window.setTimeout(() => controller.abort(), 120000);
const response = await fetch("/api/canvas/download-zip", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
signal: controller.signal,
body: JSON.stringify({
folderName,
files,
}),
const form = document.createElement("form");
form.method = "POST";
form.action = "/api/canvas/download-zip";
form.style.display = "none";
const payloadInput = document.createElement("input");
payloadInput.type = "hidden";
payloadInput.name = "payload";
payloadInput.value = JSON.stringify({
folderName,
files,
});
form.appendChild(payloadInput);
if (!response.ok) {
const data = await response.json().catch(() => ({}));
toast.error(data?.error || "打包失败,请稍后重试");
return;
}
document.body.appendChild(form);
form.submit();
form.remove();
const zipBlob = await response.blob();
downloadBlob(zipBlob, `${folderName}.zip`);
const successCount = Number(response.headers.get("X-Download-Success-Count") || "0");
const failedCount = Number(response.headers.get("X-Download-Failed-Count") || "0");
const totalCount = files.length;
if (failedCount > 0) {
toast.warning(`已打包 ${successCount} 张,失败 ${failedCount} 张`);
} else {
toast.success(`已下载压缩包,包含 ${successCount || totalCount} 张图片`);
}
} catch (error) {
if (error instanceof DOMException && error.name === "AbortError") {
toast.error("打包超时,请减少图片数量后重试");
} else {
toast.error("下载失败,请稍后重试");
}
toast.success("已开始打包下载,请留意浏览器下载栏");
} catch (_error) {
toast.error("下载失败,请稍后重试");
} finally {
if (timeoutId) {
window.clearTimeout(timeoutId);
}
setIsDownloadSubmitting(false);
window.setTimeout(() => {
setIsDownloadSubmitting(false);
}, 800);
}
}, [isDownloadSubmitting, selectedImageNodes]);