npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@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)
  • Buffer
  • Readable(Node 可读流)
  • File(浏览器环境下的 File 对象)
  • ArrayBuffer
  • Uint8Array

内部会自动识别其对应的 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 / height
    • aspectRatio:格式化宽高比(例如 16:94:3),由 @libeilong/funccalculateAspectRatio 计算
  • 方法:

    • 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:音频信息读取

AudioFileNormalFile 之上,利用 FFprobeHelper 解析音频文件信息:

  • metadata?: MediaInfo

    • duration:时长(秒)
    • bitrate:比特率
    • formatsizeaudioCodecmimeType
  • 方法:

    • 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:视频信息读取

VideoFileAudioFile 类似,但会额外解析视频相关字段:

  • metadata?: MediaInfo

    • width / height
    • fps:帧率
    • videoCodec / audioCodec
    • 其他同 AudioFile
  • getter:

    • width / height
    • aspectRatio:格式化宽高比(内部使用 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?: number
  • bitrate?: number
  • fps?: number
  • format?: string
  • size?: number:文件大小(字节)
  • audioCodec?: string
  • videoCodec?: string
  • mimeType?: string

方法

  • FFprobeHelper.isAvailable(): Promise<boolean>
    • 检查 ffprobe 是否可用(是否能访问内置可执行文件)
  • FFprobeHelper.getMediaInfo(filePath: string): Promise<MediaInfo>
    • 调用 ffprobe,解析其 JSON 输出并转换为 MediaInfo

简单示例:

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