39 lines
1,012 B
TypeScript
39 lines
1,012 B
TypeScript
import fs from "node:fs/promises";
|
|
import path from "node:path";
|
|
|
|
function normalizeKey(relKey: string): string {
|
|
return relKey
|
|
.replace(/^\/+/, "")
|
|
.split("/")
|
|
.filter(Boolean)
|
|
.map(segment => segment.replace(/[^a-zA-Z0-9._-]/g, "_"))
|
|
.join("/");
|
|
}
|
|
|
|
function getUploadRoot() {
|
|
return path.resolve(process.cwd(), "uploads");
|
|
}
|
|
|
|
function getPublicUrl(key: string) {
|
|
return `/uploads/${key}`;
|
|
}
|
|
|
|
export async function storagePut(
|
|
relKey: string,
|
|
data: Buffer | Uint8Array | string,
|
|
contentType = "application/octet-stream"
|
|
): Promise<{ key: string; url: string }> {
|
|
const key = normalizeKey(relKey);
|
|
const filePath = path.join(getUploadRoot(), key);
|
|
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
await fs.writeFile(filePath, data);
|
|
return { key, url: getPublicUrl(key) };
|
|
}
|
|
|
|
export async function storageGet(relKey: string): Promise<{ key: string; url: string; }> {
|
|
const key = normalizeKey(relKey);
|
|
return {
|
|
key,
|
|
url: getPublicUrl(key),
|
|
};
|
|
}
|