/** * 交付文件的内容存储:本地磁盘目录,一个文件一个对象,文件名就是平台生成的 file_id。 * ponytail: 单机磁盘,多实例或换机器会丢;上 stage / 生产前换成对象存储(S3 / OSS)实现同样的 put / get。 */ import { mkdir, readFile, writeFile } from 'node:fs/promises' import path from 'node:path' const FILE_ID = /^f_[0-9a-f-]{36}$/ /** * @param {{ dir: string }} opts */ export function createFileStore({ dir }) { /** @param {string} file_id */ function pathOf(file_id) { // file_id 由平台生成;这里再校验一次,保证任何输入都拼不出目录外的路径。 if (!FILE_ID.test(file_id)) throw new Error(`file store: invalid file id: ${file_id}`) return path.join(dir, file_id) } return { /** * @param {string} file_id * @param {Buffer} body */ async put(file_id, body) { await mkdir(dir, { recursive: true }) await writeFile(pathOf(file_id), body, { flag: 'wx' }) }, /** * @param {string} file_id * @returns {Promise} */ async get(file_id) { return readFile(pathOf(file_id)) }, } }