fenghuo/packages/tus/src/utils/kvstores/FileKvStore.ts

94 lines
2.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import fs from 'node:fs/promises'
import path from 'node:path'
import type {KvStore} from './Types'
import type {Upload} from '../models'
/**
* 文件键值存储FileKvStore
*
* @description 基于文件系统的键值对存储实现,专门用于存储上传文件的元数据
* @remarks
* - 将上传文件的JSON元数据存储在磁盘上与上传文件同目录
* - 使用队列机制确保并发安全,每次仅处理一个操作
*
* @typeparam T 存储的数据类型默认为Upload类型
*/
export class FileKvStore<T = Upload> implements KvStore<T> {
/** 存储目录路径 */
directory: string
/**
* 构造函数
*
* @param path 指定存储元数据的目录路径
*/
constructor(path: string) {
this.directory = path
}
/**
* 根据键获取存储的值
*
* @param key 键名
* @returns 返回对应的值如果不存在则返回undefined
*/
async get(key: string): Promise<T | undefined> {
try {
// 读取对应键的JSON文件
const buffer = await fs.readFile(this.resolve(key), 'utf8')
// 解析JSON并返回
return JSON.parse(buffer as string)
} catch {
// 文件不存在或读取失败时返回undefined
return undefined
}
}
/**
* 存储键值对
* @param key 键名
* @param value 要存储的值
*/
async set(key: string, value: T): Promise<void> {
// 将值转换为JSON并写入文件
await fs.writeFile(this.resolve(key), JSON.stringify(value))
}
/**
* 删除指定键的值
*
* @param key 要删除的键名
*/
async delete(key: string): Promise<void> {
// 删除对应的JSON文件
await fs.rm(this.resolve(key))
}
/**
* 列出所有存储的键
*
* @returns 返回已存储的键名数组
*/
async list(): Promise<Array<string>> {
// 读取目录中的所有文件
const files = await fs.readdir(this.directory)
// 对文件名进行排序
const sorted = files.sort((a, b) => a.localeCompare(b))
// 提取文件名(不包含扩展名)
const name = (file: string) => path.basename(file, '.json')
// 过滤出有效的tus文件ID
// 仅保留成对出现的文件(文件名相同,一个有.json扩展名
return sorted.filter(
(file, idx) => idx < sorted.length - 1 && name(file) === name(sorted[idx + 1])
)
}
/**
* 将键转换为完整的文件路径
*
* @param key 键名
* @returns 返回完整的文件路径
* @private
*/
private resolve(key: string): string {
// 将键名转换为完整的JSON文件路径
return path.resolve(this.directory, `${key}.json`)
}
}