@libeilong/node-file
v0.1.1
Published
针对 Node 环境封装的一组文件 / 媒体处理工具,统一抽象多种资源输入(URL、本地路径、Buffer、Stream、Base64 等),并提供:
Readme
@libeilong/node-file
针对 Node 环境封装的一组文件 / 媒体处理工具,统一抽象多种资源输入(URL、本地路径、Buffer、Stream、Base64 等),并提供:
NormalFile:统一的文件抽象,支持自动识别类型、扩展名、MIME、大小等ImageFile/AudioFile/VideoFile:在NormalFile基础上获取媒体元信息DownloadManager:带本地缓存与清理策略的下载工具FFprobeHelper:基于ffprobe的音视频信息解析UploadAdapter:文件上传适配抽象,方便对接各类对象存储服务
适合在脚本、CLI、服务端(如 NestJS)项目中统一处理文件和媒体资源。
安装
pnpm add @libeilong/node-file
# 或
npm install @libeilong/node-file
# 或
yarn add @libeilong/node-file运行环境要求:Node.js
>= 10
peerDependencies
本包声明了:
@nestjs/common(内部主要用于日志输出Logger,即使不是 Nest 项目也可安全使用)
主要依赖
内部使用的关键依赖(已作为 dependencies)包括:
axios:网络请求ffmpeg-ffprobe-static:提供ffprobe可执行文件@napi-rs/image:高性能图片信息读取@libeilong/func:部分通用工具函数(如宽高比计算)
使用时按正常方式安装本包即可,无需额外安装上述依赖。
核心概念
ResourceInput & ResourceType
ResourceInput 表示可以被本库统一处理的资源输入类型:
string- URL:
http:///https:///ftp:// - 本地文件路径
- Base64 字符串(支持
data:URL 和纯 base64)
- URL:
BufferReadable(Node 可读流)File(浏览器环境下的File对象)ArrayBufferUint8Array
内部会自动识别其对应的 ResourceType:
'url' | 'path' | 'buffer' | 'stream' | 'file' | 'arraybuffer' | 'uint8array' | 'base64'
NormalFile:统一文件抽象
NormalFile 是整个包的基础类,用于封装一个“文件资源”的生命周期:
- 自动识别资源类型与来源(URL / 本地路径 / Buffer / 流 / Base64 等)
- 尽可能推断:
extension:扩展名mimetype:MIME 类型size:大小(字节)
- 提供统一 API 获取:
getBuffer():获取完整Buffer(带缓存)getStream():获取可读流getPath():获取本地路径(URL 会下载到临时目录)
- 管理临时资源:
- 自动维护
.cache/temp下的临时文件 - 通过
clear()主动清理缓存的临时文件 / Buffer
- 自动维护
- 预留
oss字段,用于保存上传后得到的url/key
一个典型示例:
import { NormalFile } from '@libeilong/node-file'
// 你可以传入 URL、本地路径、Buffer、Stream、Base64 等
const file = new NormalFile('https://example.com/image.jpg')
// 基本信息(部分字段可能是推断得到的)
console.log(file.extension) // 'jpg'
console.log(file.mimetype) // 'image/jpeg'
console.log(file.size) // 若可立即获取则有值,否则为 undefined,稍后会延迟计算
// 获取 Buffer(内部会根据资源类型自动处理)
const buffer = await file.getBuffer()
// 获取本地路径(如果是 URL,会先下载到临时目录)
const localPath = await file.getPath()
// 处理完成后,主动清理临时资源
file.clear()在上传场景中,你可以对 NormalFile 做统一的前置处理(校验大小 / 类型、计算哈希、生成缩略图等),然后交给自定义的 UploadAdapter 完成上传。
媒体子类
在 NormalFile 基础上,本包针对图片、音频、视频提供了更高层的封装。
所有子类都支持 ResourceInput 作为构造参数,也提供 create / 静态工具方法简化使用。
ImageFile:图片信息读取
ImageFile 使用 @napi-rs/image 高性能读取图片元信息,适合在服务端大量处理图片时使用。
属性:
metadata?: { width?: number; height?: number; format?: string; size: number; mime?: string }width/height:宽高(不存在时为0)aspectRatioValue:数值宽高比width / heightaspectRatio:格式化宽高比(例如16:9、4:3),由@libeilong/func的calculateAspectRatio计算
方法:
getMetadata():读取并缓存图片元信息ImageFile.imageMetadata(resource):静态方法,一步拿到元信息 + 宽高比ImageFile.create(resource | ImageFile):如果已经是ImageFile实例则直接返回
使用示例:
import { ImageFile } from '@libeilong/node-file'
const img = ImageFile.create('https://example.com/banner.png')
const meta = await img.getMetadata()
console.log(meta.width, meta.height, meta.mime)
console.log('aspect ratio:', img.aspectRatio) // 比如 '16:9'
// 更简洁的静态工具用法
const full = await ImageFile.imageMetadata('https://example.com/banner.png')
// full 包含 width / height / format / size / mime / aspectRatio 等字段AudioFile:音频信息读取
AudioFile 在 NormalFile 之上,利用 FFprobeHelper 解析音频文件信息:
metadata?: MediaInfoduration:时长(秒)bitrate:比特率format、size、audioCodec、mimeType等
方法:
getMetadata():通过 ffprobe 获取音频信息,并在成功后调用clear()清理临时文件AudioFile.create(resource | AudioFile):工厂方法
import { AudioFile } from '@libeilong/node-file'
const audio = AudioFile.create('/path/to/song.mp3')
const meta = await audio.getMetadata()
console.log(meta.duration, meta.audioCodec, meta.bitrate)VideoFile:视频信息读取
VideoFile 与 AudioFile 类似,但会额外解析视频相关字段:
metadata?: MediaInfowidth/heightfps:帧率videoCodec/audioCodec- 其他同
AudioFile
getter:
width/heightaspectRatio:格式化宽高比(内部使用calculateAspectRatio)
静态方法:
VideoFile.videoMetadata(resource):一步拿到媒体信息 + 宽高比VideoFile.create(resource | VideoFile)
import { VideoFile } from '@libeilong/node-file'
const video = VideoFile.create('https://example.com/video.mp4')
const info = await video.getMetadata()
console.log(info.duration, info.width, info.height, info.fps)
const full = await VideoFile.videoMetadata('https://example.com/video.mp4')
console.log(full.aspectRatio) // 例如 '16:9'注意:音视频相关功能依赖
ffmpeg-ffprobe-static内置的ffprobe可执行文件,必须在可运行 ffprobe 的环境中使用(例如常规服务器、Docker 镜像等)。
DownloadManager:带缓存的下载器
DownloadManager 用于按 URL 下载文件到本地,并在 .cache/download 目录下做缓存管理:
- 使用 URL 计算 md5 作为缓存 key,保留原始扩展名
- 已下载文件会复用,不会重复下载
- 默认最大缓存体积:
1GB - 超出上限后按照访问时间(LRU)清理最久未访问的文件
主要方法
DownloadManager.download(url): Promise<string>- 下载文件并返回本地路径
- 如已缓存则只更新访问时间并直接返回原路径
DownloadManager.getCacheStatus(): Promise<{ totalSize: number; fileCount: number; maxSize: number }>- 获取当前缓存占用情况
DownloadManager.clearCache(): Promise<void>- 手动清空所有缓存文件
使用示例
import { DownloadManager } from '@libeilong/node-file'
// 下载并缓存
const localPath = await DownloadManager.download('https://example.com/video.mp4')
console.log('file saved at:', localPath)
// 查看缓存状态
const status = await DownloadManager.getCacheStatus()
console.log(status.totalSize, status.fileCount)
// 手动清空缓存
await DownloadManager.clearCache()在处理远程媒体文件时,你可以先通过 DownloadManager 获取本地路径,再交给 VideoFile / AudioFile 做后续解析;也可以直接把 URL 交给 VideoFile,内部会走统一的下载逻辑。
FFprobeHelper:音视频信息工具
FFprobeHelper 是对 ffprobe 命令行工具的轻量封装,用于从音视频文件中提取结构化信息。
MediaInfo 结构
MediaInfo 大致包含:
duration: number:时长(秒)width?: number/height?: numberbitrate?: numberfps?: numberformat?: stringsize?: number:文件大小(字节)audioCodec?: stringvideoCodec?: stringmimeType?: string
方法
FFprobeHelper.isAvailable(): Promise<boolean>- 检查 ffprobe 是否可用(是否能访问内置可执行文件)
FFprobeHelper.getMediaInfo(filePath: string): Promise<MediaInfo>- 调用 ffprobe,解析其 JSON 输出并转换为
MediaInfo
- 调用 ffprobe,解析其 JSON 输出并转换为
简单示例:
import { FFprobeHelper } from '@libeilong/node-file'
if (!(await FFprobeHelper.isAvailable())) {
throw new Error('ffprobe not available in current environment')
}
const info = await FFprobeHelper.getMediaInfo('/path/to/video.mp4')
console.log(info.duration, info.fps, info.mimeType)在大多数场景下,你可以直接使用 AudioFile / VideoFile,只有在需要更底层控制时再直接使用 FFprobeHelper。
UploadAdapter:上传适配抽象
UploadAdapter 是一个抽象类,用来规范“如何把 NormalFile 上传到某个对象存储服务”:
import { NormalFile, UploadAdapter } from '@libeilong/node-file'
class MyOssAdapter extends UploadAdapter {
async upload(file: NormalFile) {
const buffer = await file.getBuffer()
// 在这里调用具体的 SDK 上传,例如阿里云 OSS / 七牛 / S3 等
const key = `uploads/${Date.now()}.${file.extension || 'bin'}`
// await ossClient.put(key, buffer, { contentType: file.mimetype })
const url = `https://cdn.example.com/${key}`
// 你可以顺便把结果写回 file.oss,方便后续使用
file.oss = { key, url }
return { key, url }
}
}
// 使用示例
const file = new NormalFile('https://example.com/avatar.png')
const adapter = new MyOssAdapter()
const result = await adapter.upload(file)
console.log(result.key, result.url)借助 UploadAdapter,可以在业务层只关心“上传能力接口”,而不关心底层资源是 URL / 文件路径 / Buffer,全部交由 NormalFile 统一处理。
典型使用场景
- 在 Node 脚本 / CLI 中统一处理各种来源的文件:本地路径、URL、Base64、Buffer、Stream 等
- 在 后端服务(如 NestJS) 中实现:
- 上传前文件校验(大小、类型、分辨率、时长等)
- 媒体信息提取(图片宽高、视频时长和帧率、音频码率等)
- 下载 + 缓存远程媒体资源
- 构建 媒体处理流水线:
NormalFile(统一输入) →ImageFile/AudioFile/VideoFile(信息解析) → 自定义UploadAdapter(上传到 OSS / CDN)
License
MIT
