import "server-only"; import { uploadFile } from "@/lib/storage/service"; const DATA_IMAGE_URL_PATTERN = /^data:(image\/[a-z0-9.+-]+);base64,([a-z0-9+/=\s]+)$/i; const MIME_TYPE_EXTENSION_MAP: Record = { "image/jpeg": "jpg", "image/jpg": "jpg", "image/png": "png", "image/webp": "webp", "image/gif": "gif", "image/bmp": "bmp", "image/tiff": "tiff", "image/svg+xml": "svg", }; function normalizeImageMimeType(mimeType: string) { return String(mimeType || "").trim().toLowerCase(); } function resolveImageExtension(mimeType: string) { const normalized = normalizeImageMimeType(mimeType); return MIME_TYPE_EXTENSION_MAP[normalized] || normalized.split("/")[1] || "png"; } function toArrayBuffer(buffer: Buffer) { return buffer.buffer.slice( buffer.byteOffset, buffer.byteOffset + buffer.byteLength ) as ArrayBuffer; } export function parseDataImageUrl(raw: string) { const trimmed = String(raw || "").trim(); const match = trimmed.match(DATA_IMAGE_URL_PATTERN); if (!match) return null; const mimeType = normalizeImageMimeType(match[1]); const base64Payload = match[2].replace(/\s+/g, ""); return { mimeType, base64Payload, extension: resolveImageExtension(mimeType), }; } export async function uploadDataImageUrl(params: { imageUrl: string; prefix: string; }) { const parsed = parseDataImageUrl(params.imageUrl); if (!parsed) { throw new Error("图片必须是有效的 data:image;base64 格式"); } const buffer = Buffer.from(parsed.base64Payload, "base64"); const filename = `${params.prefix}-${Date.now()}-${Math.random() .toString(36) .slice(2, 8)}.${parsed.extension}`; const uploaded = await uploadFile(filename, toArrayBuffer(buffer)); return uploaded.url; } export async function ensurePublicImageUrl(params: { imageUrl: string; prefix: string; requestOrigin?: string; }) { const trimmed = String(params.imageUrl || "").trim(); if (!trimmed) { throw new Error("缺少输入图片"); } if (/^https?:\/\//i.test(trimmed)) { return trimmed; } if (params.requestOrigin && trimmed.startsWith("/")) { return new URL(trimmed, params.requestOrigin).toString(); } if (trimmed.startsWith("data:")) { return uploadDataImageUrl({ imageUrl: trimmed, prefix: params.prefix, }); } throw new Error("图片必须是公网 URL、站内相对路径或 data:image;base64"); }