83 lines
2.5 KiB
TypeScript
83 lines
2.5 KiB
TypeScript
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import {
|
|
type WechatUploadAsset,
|
|
detectImageFormatFromBuffer,
|
|
} from "./wechat-image-processor.ts";
|
|
|
|
export type { WechatUploadAsset };
|
|
|
|
const MIME_TYPES_BY_EXT: Record<string, string> = {
|
|
".jpg": "image/jpeg",
|
|
".jpeg": "image/jpeg",
|
|
".png": "image/png",
|
|
".gif": "image/gif",
|
|
".webp": "image/webp",
|
|
".bmp": "image/bmp",
|
|
".tiff": "image/tiff",
|
|
".tif": "image/tiff",
|
|
".svg": "image/svg+xml",
|
|
".ico": "image/x-icon",
|
|
};
|
|
|
|
export async function loadUploadAsset(
|
|
imagePath: string,
|
|
baseDir?: string,
|
|
): Promise<WechatUploadAsset> {
|
|
let fileBuffer: Buffer;
|
|
let filename: string;
|
|
let contentType: string;
|
|
let fileSize = 0;
|
|
let fileExt = "";
|
|
|
|
if (imagePath.startsWith("http://") || imagePath.startsWith("https://")) {
|
|
const response = await fetch(imagePath);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to download image: ${imagePath}`);
|
|
}
|
|
const buffer = await response.arrayBuffer();
|
|
if (buffer.byteLength === 0) {
|
|
throw new Error(`Remote image is empty: ${imagePath}`);
|
|
}
|
|
fileBuffer = Buffer.from(buffer);
|
|
fileSize = buffer.byteLength;
|
|
const urlPath = imagePath.split("?")[0]!;
|
|
filename = path.basename(urlPath) || "image.jpg";
|
|
fileExt = path.extname(filename).toLowerCase();
|
|
contentType = response.headers.get("content-type") || "image/jpeg";
|
|
} else {
|
|
const resolvedPath = path.isAbsolute(imagePath)
|
|
? imagePath
|
|
: path.resolve(baseDir || process.cwd(), imagePath);
|
|
|
|
if (!fs.existsSync(resolvedPath)) {
|
|
throw new Error(`Image not found: ${resolvedPath}`);
|
|
}
|
|
const stats = fs.statSync(resolvedPath);
|
|
if (stats.size === 0) {
|
|
throw new Error(`Local image is empty: ${resolvedPath}`);
|
|
}
|
|
fileSize = stats.size;
|
|
fileBuffer = fs.readFileSync(resolvedPath);
|
|
filename = path.basename(resolvedPath);
|
|
fileExt = path.extname(filename).toLowerCase();
|
|
contentType = MIME_TYPES_BY_EXT[fileExt] || "image/jpeg";
|
|
}
|
|
|
|
const detected = detectImageFormatFromBuffer(fileBuffer);
|
|
if (detected && detected.contentType !== contentType) {
|
|
console.error(`[wechat-api] Format mismatch: ${filename} declared as ${contentType}, actual ${detected.contentType}`);
|
|
contentType = detected.contentType;
|
|
fileExt = detected.fileExt;
|
|
filename = `${path.basename(filename, path.extname(filename))}${detected.fileExt}`;
|
|
}
|
|
|
|
return {
|
|
buffer: fileBuffer,
|
|
filename,
|
|
contentType,
|
|
fileExt,
|
|
fileSize,
|
|
};
|
|
}
|