60 lines
1.9 KiB
JavaScript
60 lines
1.9 KiB
JavaScript
import { copyFile, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
||
import path from "node:path";
|
||
|
||
const sourceRoot = process.argv[2];
|
||
const targetRoot = process.env.UPLOAD_DIR || process.argv[3];
|
||
if (!sourceRoot || !targetRoot) {
|
||
throw new Error(
|
||
"用法:UPLOAD_DIR=/data/koc/uploads npm run storage:import -- /path/to/r2-export",
|
||
);
|
||
}
|
||
|
||
const contentTypes = {
|
||
".avif": "image/avif",
|
||
".gif": "image/gif",
|
||
".jpeg": "image/jpeg",
|
||
".jpg": "image/jpeg",
|
||
".png": "image/png",
|
||
".webp": "image/webp",
|
||
};
|
||
|
||
let copied = 0;
|
||
async function walk(directory) {
|
||
const entries = await readdir(directory, { withFileTypes: true });
|
||
for (const entry of entries) {
|
||
const absolute = path.join(directory, entry.name);
|
||
if (entry.isDirectory()) {
|
||
await walk(absolute);
|
||
continue;
|
||
}
|
||
if (entry.name.endsWith(".metadata.json")) continue;
|
||
const relative = path.relative(sourceRoot, absolute);
|
||
if (relative.startsWith("..") || path.isAbsolute(relative)) {
|
||
throw new Error("导入目录越界");
|
||
}
|
||
const destination = path.join(targetRoot, relative);
|
||
await mkdir(path.dirname(destination), { recursive: true });
|
||
await copyFile(absolute, destination);
|
||
const sourceMetadata = `${absolute}.metadata.json`;
|
||
const metadataDestination = `${destination}.metadata.json`;
|
||
let metadata;
|
||
try {
|
||
metadata = JSON.parse(await readFile(sourceMetadata, "utf8"));
|
||
} catch {
|
||
metadata = {
|
||
contentType:
|
||
contentTypes[path.extname(entry.name).toLowerCase()] ||
|
||
"application/octet-stream",
|
||
customMetadata: { source: "r2-export" },
|
||
uploadedAt: new Date().toISOString(),
|
||
};
|
||
}
|
||
await writeFile(metadataDestination, JSON.stringify(metadata), "utf8");
|
||
copied += 1;
|
||
}
|
||
}
|
||
|
||
await mkdir(targetRoot, { recursive: true });
|
||
await walk(sourceRoot);
|
||
console.info(`imported objects: ${copied}`);
|