针对 Node 环境封装的一组文件 / 媒体处理工具,统一抽象多种资源输入(URL、本地路径、Buffer、Stream、Base64 等),并提供:
npm install @libeilong/node-file针对 Node 环境封装的一组文件 / 媒体处理工具,统一抽象多种资源输入(URL、本地路径、Buffer、Stream、Base64 等),并提供:
- NormalFile:统一的文件抽象,支持自动识别类型、扩展名、MIME、大小等
- ImageFile / AudioFile / VideoFile:在 NormalFile 基础上获取媒体元信息
- DownloadManager:带本地缓存与清理策略的下载工具
- FFprobeHelper:基于 ffprobe 的音视频信息解析
- UploadAdapter:文件上传适配抽象,方便对接各类对象存储服务
适合在脚本、CLI、服务端(如 NestJS)项目中统一处理文件和媒体资源。
``bash`
pnpm add @libeilong/node-file或
npm install @libeilong/node-file或
yarn add @libeilong/node-file
> 运行环境要求:Node.js >= 10
本包声明了:
- @nestjs/common(内部主要用于日志输出 Logger,即使不是 Nest 项目也可安全使用)
内部使用的关键依赖(已作为 dependencies)包括:
- axios:网络请求ffmpeg-ffprobe-static
- :提供 ffprobe 可执行文件@napi-rs/image
- :高性能图片信息读取@libeilong/func
- :部分通用工具函数(如宽高比计算)
使用时按正常方式安装本包即可,无需额外安装上述依赖。
---
ResourceInput 表示可以被本库统一处理的资源输入类型:
- stringhttp://
- URL: / https:// / ftp://data:
- 本地文件路径
- Base64 字符串(支持 URL 和纯 base64)Buffer
- Readable
- (Node 可读流)File
- (浏览器环境下的 File 对象)ArrayBuffer
- Uint8Array
-
内部会自动识别其对应的 ResourceType:
- 'url' | 'path' | 'buffer' | 'stream' | 'file' | 'arraybuffer' | 'uint8array' | 'base64'
NormalFile 是整个包的基础类,用于封装一个“文件资源”的生命周期:
- 自动识别资源类型与来源(URL / 本地路径 / Buffer / 流 / Base64 等)
- 尽可能推断:
- extension:扩展名mimetype
- :MIME 类型size
- :大小(字节)getBuffer()
- 提供统一 API 获取:
- :获取完整 Buffer(带缓存)getStream()
- :获取可读流getPath()
- :获取本地路径(URL 会下载到临时目录).cache/temp
- 管理临时资源:
- 自动维护 下的临时文件clear()
- 通过 主动清理缓存的临时文件 / Buffeross
- 预留 字段,用于保存上传后得到的 url / key
一个典型示例:
`ts
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 使用 @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 实例则直接返回
使用示例:
`ts
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 在 NormalFile 之上,利用 FFprobeHelper 解析音频文件信息:
- metadata?: MediaInfoduration
- :时长(秒)bitrate
- :比特率format
- 、size、audioCodec、mimeType 等
- 方法:
- getMetadata():通过 ffprobe 获取音频信息,并在成功后调用 clear() 清理临时文件AudioFile.create(resource | AudioFile)
- :工厂方法
`ts
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 与 AudioFile 类似,但会额外解析视频相关字段:
- metadata?: MediaInfowidth
- / heightfps
- :帧率videoCodec
- / audioCodecAudioFile
- 其他同
- getter:
- width / heightaspectRatio
- :格式化宽高比(内部使用 calculateAspectRatio)
- 静态方法:
- VideoFile.videoMetadata(resource):一步拿到媒体信息 + 宽高比VideoFile.create(resource | VideoFile)
-
`ts
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 用于按 URL 下载文件到本地,并在 .cache/download 目录下做缓存管理:
- 使用 URL 计算 md5 作为缓存 key,保留原始扩展名
- 已下载文件会复用,不会重复下载
- 默认最大缓存体积:1GB
- 超出上限后按照访问时间(LRU)清理最久未访问的文件
- DownloadManager.download(url): PromiseDownloadManager.getCacheStatus(): Promise<{ totalSize: number; fileCount: number; maxSize: number }>
- 下载文件并返回本地路径
- 如已缓存则只更新访问时间并直接返回原路径
- DownloadManager.clearCache(): Promise
- 获取当前缓存占用情况
-
- 手动清空所有缓存文件
`ts
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 是对 ffprobe 命令行工具的轻量封装,用于从音视频文件中提取结构化信息。
MediaInfo 大致包含:
- duration: number:时长(秒)width?: number
- / height?: numberbitrate?: number
- fps?: number
- format?: string
- size?: number
- :文件大小(字节)audioCodec?: string
- videoCodec?: string
- mimeType?: string
-
- FFprobeHelper.isAvailable(): PromiseFFprobeHelper.getMediaInfo(filePath: string): Promise
- 检查 ffprobe 是否可用(是否能访问内置可执行文件)
- MediaInfo
- 调用 ffprobe,解析其 JSON 输出并转换为
简单示例:
`ts
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 是一个抽象类,用来规范“如何把 NormalFile 上传到某个对象存储服务”:
`ts
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)
---
MIT