调用 API 前必须先获取 API Key
所有 API 请求均需通过 X-API-Key 请求头进行身份认证。没有有效的 API Key,任何端点都无法调用。
环境要求
- Node.js 18+
- image-size 库(获取图片尺寸)
安装依赖
npm install image-size
完整示例代码
import fs from "node:fs";
import path from "node:path";
import sizeOf from "image-size";
const API_KEY = process.env.IMGROUTE_API_KEY || "sk-ir-your-key-here";
const BASE_URL = "https://imgroute.com/api/v1";
async function getImageInfo(filePath) {
const stats = fs.statSync(filePath);
const dimensions = sizeOf(filePath);
const name = path.basename(filePath);
const ext = path.extname(filePath).slice(1).toLowerCase();
const mimeTypes = { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", gif: "image/gif", webp: "image/webp" };
return { name, size: stats.size, width: dimensions.width, height: dimensions.height, mimeType: mimeTypes[ext] || "image/jpeg" };
}
async function uploadImage(filePath, albumId) {
const info = await getImageInfo(filePath);
const presignResponse = await fetch(BASE_URL + "/upload", {
method: "POST",
headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
file_name: info.name,
file_size: info.size,
mime_type: info.mimeType,
width: info.width,
height: info.height,
...(albumId && { album_id: albumId })
})
});
const presignData = await presignResponse.json();
if (!presignData.success) throw new Error("预签名失败: " + presignData.error);
const { upload_url, cdn_url } = presignData.data;
const fileBuffer = fs.readFileSync(filePath);
const formData = new FormData();
formData.append("file", new Blob([fileBuffer], { type: info.mimeType }), info.name);
const uploadResponse = await fetch(upload_url, { method: "POST", body: formData });
const uploadData = await uploadResponse.json();
if (!uploadData.success) throw new Error("上传失败: " + uploadData.error);
return cdn_url;
}
async function main() {
try {
const cdnUrl = await uploadImage("./cat.jpg");
console.log("上传成功: " + cdnUrl);
} catch (error) {
console.error("上传失败: " + error);
}
}
main();
使用 axios 的示例
import axios from "axios";
import fs from "node:fs";
import sizeOf from "image-size";
const API_KEY = process.env.IMGROUTE_API_KEY;
const BASE_URL = "https://imgroute.com/api/v1";
async function uploadImage(filePath) {
const stats = fs.statSync(filePath);
const dimensions = sizeOf(filePath);
const name = path.basename(filePath);
const presign = await axios.post(BASE_URL + "/upload", {
file_name: name,
file_size: stats.size,
mime_type: "image/jpeg",
width: dimensions.width,
height: dimensions.height
}, { headers: { "X-API-Key": API_KEY, "Content-Type": "application/json" } });
const { upload_url, cdn_url } = presign.data.data;
const fileStream = fs.createReadStream(filePath);
await axios.post(upload_url, fileStream, { headers: { "Content-Type": "image/jpeg" } });
return cdn_url;
}
批量上传示例
import fs from "node:fs";
import path from "node:path";
async function batchUpload(directory) {
const files = fs.readdirSync(directory).filter(f => [".jpg", ".jpeg", ".png"].some(ext => f.endsWith(ext)));
const results = [];
for (const file of files) {
try {
const url = await uploadImage(path.join(directory, file));
results.push({ file, url, status: "success" });
} catch (error) {
results.push({ file, error: String(error), status: "failed" });
}
}
return results;
}
const results = await batchUpload("./images");
results.forEach(r => console.log(r.status === "success" ? "[OK] " + r.file + ": " + r.url : "[FAIL] " + r.file + ": " + r.error));
常见问题
Q: image-size 获取 SVG 尺寸失败?
SVG 等特殊格式可能需要特殊处理:
import { readFileSync } from "node:fs";
function getSvgSize(filePath) {
const content = readFileSync(filePath, "utf-8");
const match = content.match(/width="(\d+)" height="(\d+)"/);
if (match) return { width: parseInt(match[1]), height: parseInt(match[2]) };
throw new Error("无法解析 SVG 尺寸");
}
Q: 如何处理大文件上传?
使用流式上传避免内存问题:
async function uploadLargeFile(filePath) {
const fileStream = fs.createReadStream(filePath);
const formData = new FormData();
formData.append("file", fileStream);
const response = await fetch(upload_url, { method: "POST", body: formData });
return response.json();
}