倍率问题和图片问题调整

This commit is contained in:
andy committed 2026-09-23 13:33:47 +08:00
1 parent f1993eb388
commit 3f29ba716a
20 files changed
+1210 -24

No files matched your search

+37 -1
View File
@@ -19,7 +19,7 @@ export async function downloadFilesAsZip(files: DownloadableFile[], archiveName:
const response = await fetch(file.url, { credentials: "same-origin" });
if (!response.ok) throw new Error(`下载第 ${index + 1} 个图层失败`);
const data = new Uint8Array(await response.arrayBuffer());
const safeName = uniqueFileName(sanitizeFileName(file.name) || `layer-${index}.png`, usedNames);
const safeName = uniqueFileName(imageFileName(sanitizeFileName(file.name) || `layer-${index}`, data), usedNames);
entries.push({ name: new TextEncoder().encode(safeName), data, crc: crc32(data), offset: 0 });
}
const blob = zipBlob(entries);
@@ -93,6 +93,42 @@ function sanitizeFileName(value: string) {
return value.trim().replace(/[\\/:*?"<>|\u0000-\u001f]/g, "-").replace(/^\.+/, "").slice(0, 120);
}
function imageFileName(name: string, data: Uint8Array) {
let extensions: string[] | undefined;
let preferred: string | undefined;
if (data.length >= 8 && data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47 && data[4] === 0x0d && data[5] === 0x0a && data[6] === 0x1a && data[7] === 0x0a) {
extensions = ["png"];
preferred = "png";
} else if (data.length >= 3 && data[0] === 0xff && data[1] === 0xd8 && data[2] === 0xff) {
extensions = ["jpg", "jpeg", "jpe"];
preferred = "jpg";
} else if (data.length >= 14 && asciiAt(data, 0, "RIFF") && asciiAt(data, 8, "WEBPVP")) {
extensions = ["webp"];
preferred = "webp";
} else if (data.length >= 6 && (asciiAt(data, 0, "GIF87a") || asciiAt(data, 0, "GIF89a"))) {
extensions = ["gif"];
preferred = "gif";
} else if (data.length >= 2 && asciiAt(data, 0, "BM")) {
extensions = ["bmp"];
preferred = "bmp";
} else if (data.length >= 4 && data[0] === 0 && data[1] === 0 && (data[2] === 1 || data[2] === 2) && data[3] === 0) {
extensions = ["ico"];
preferred = "ico";
}
if (!preferred || !extensions) return name;
const dot = name.lastIndexOf(".");
const current = dot > 0 ? name.slice(dot + 1) : "";
if (extensions.includes(current.toLowerCase())) return name;
return `${dot > 0 ? name.slice(0, dot) : name}.${preferred}`;
}
function asciiAt(data: Uint8Array, offset: number, value: string) {
for (let index = 0; index < value.length; index += 1) {
if (data[offset + index] !== value.charCodeAt(index)) return false;
}
return true;
}
function uniqueFileName(name: string, used: Set<string>) {
if (!used.has(name)) {
used.add(name);