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 🙏

© 2026 – Pkg Stats / Ryan Hefner

luoyu-oss-unified

v0.0.8

Published

luoyu-oss-unified 是一个统一的对象存储服务(OSS)客户端库,支持阿里云、腾讯云、七牛云、MinIO等多种云服务商。提供一致的API接口,简化多平台对象存储集成,支持分片上传、断点续传等高级功能,适用于Node.js和Web应用开发。

Readme

luoyu-oss-unified - 统一对象存储客户端

一个统一的多平台对象存储客户端,支持 MinIO、阿里云、腾讯云、七牛云等多种对象存储服务。

特性

  • 🚀 统一的 API 接口,支持多种对象存储服务
  • 📦 轻量级设计,易于集成
  • 🔧 支持上传、下载、删除、列表、目录操作等功能
  • 🔄 支持分片上传和断点续传
  • 🛡️ TypeScript 支持,类型安全
  • ⚡ 事件监听机制,支持进度监控和错误处理

安装

npm install luoyu-oss-unified

快速开始

基本使用

import { OSSClient, OSSProvider } from 'luoyu-oss-unified';

// MinIO 配置
const minioConfig = {
  provider: OSSProvider.MINIO,
  endpoint: 'http://your-minio-server.com',
  accessKeyId: 'your-access-key',
  accessKeySecret: 'your-secret-key',
  bucket: 'your-bucket',
  region: 'us-east-1',
};

// 创建客户端
const ossClient = new OSSClient(minioConfig);

// 上传文件
await ossClient.upload({
  path: 'images/photo.jpg',
  file: fs.readFileSync('./photo.jpg'),
  contentType: 'image/jpeg',
});

七牛云配置示例

const qiniuConfig = {
  provider: OSSProvider.QINIU,
  accessKeyId: 'your-access-key',
  accessKeySecret: 'your-secret-key',
  bucket: 'your-bucket',
  region: 'z0', // z0: 华东, z1: 华北, z2: 华南, na0: 北美, as0: 新加坡
  domain: 'your-domain.qiniudn.com',
};

阿里云配置示例

const aliyunConfig: OSSConfig = {
  provider: OSSProvider.ALIYUN,
  endpoint: 'https://oss-cn-guangzhou.aliyuncs.com',
  accessKeyId: 'your-aliyun-access-key-id',
  accessKeySecret: 'your-aliyun-access-key-secret',
  bucket: 'your-bucket-name',
  region: 'oss-cn-guangzhou',
};

腾讯云配置示例

const tencentConfig: OSSConfig = {
  provider: OSSProvider.TENCENT,
  accessKeyId: 'your-tencent-access-key-id',
  accessKeySecret: 'your-tencent-access-key-secret',
  bucket: 'your-tencent-bucket-name',
  region: 'ap-guangzhou',
  domain: 'https://your-bucket-name.cos.ap-guangzhou.myqcloud.com',
};

API 文档

OSSClient

构造函数

new OSSClient(config: OSSConfig)

参数:

  • config - 配置对象

配置选项:

  • provider - 存储提供商 (MINIO, ALIYUN, TENCENT, QINIU)
  • endpoint - 服务端点
  • accessKeyId - 访问密钥 ID
  • accessKeySecret - 访问密钥
  • bucket - 存储桶名称
  • region - 区域
  • secure - 是否使用 HTTPS (默认: true)
  • domain - 自定义域名 (可选)

获取底层OSS客户端实例

const client = ossClient.getOssClient();

返回值:

  • 底层OSS客户端实例,可用于直接调用提供商特定的API

示例:

const minioClient = ossClient.getOssClient();
// 现在可以使用 minioClient 直接调用 MinIO 特定的方法

上传文件

await ossClient.upload(options: UploadOptions)

参数:

  • path - 文件路径
  • file - 文件内容 (Buffer | string | ReadableStream)
  • contentType - 内容类型 (可选)
  • mode - 上传模式 (普通/分片)
  • partSize - 分片大小 (分片上传时使用)
  • progressCallback - 进度回调函数

示例:

await ossClient.upload({
  path: 'files/document.pdf',
  file: fs.readFileSync('./document.pdf'),
  contentType: 'application/pdf',
  progressCallback: (progress) => {
    console.log(`上传进度: ${progress.percent}%`);
  },
});

下载文件

const buffer = await ossClient.download(options: DownloadOptions)

参数:

  • path - 文件路径
  • destination - 本地保存路径 (可选)

示例:

const fileBuffer = await ossClient.download({
  path: 'images/photo.jpg',
});

删除文件

await ossClient.delete(path: string)

示例:

await ossClient.delete('images/photo.jpg');

删除目录

await ossClient.deleteDirectory(path: string)

示例:

await ossClient.deleteDirectory('documents/');

列出文件

const result = await ossClient.list(options?: ListOptions)

参数:

  • prefix - 前缀过滤 (可选)
  • limit - 返回数量限制 (可选)
  • delimiter - 分隔符 (可选)
  • marker - 分页标记 (可选)

示例:

const result = await ossClient.list({
  prefix: 'images/',
  limit: 10,
});
console.log(result.objects); // 文件列表

列出所有文件

const objects = await ossClient.listAll(prefix?: string)

参数:

  • prefix - 文件前缀过滤条件 (可选)

示例:

const allFiles = await ossClient.listAll('images/');
console.log(allFiles); // 所有匹配的文件对象数组

创建目录

await ossClient.createDirectory(path: string)

示例:

await ossClient.createDirectory('documents/');

列出目录

const directories = await ossClient.listDirectories(prefix?: string)

示例:

const dirs = await ossClient.listDirectories('images/');
console.log(dirs); // 目录列表

获取签名 URL

const url = await ossClient.getSignedUrl(path: string, expires: number)

参数:

  • path - 文件路径
  • expires - 过期时间 (秒,默认: 3600)

示例:

const url = await ossClient.getSignedUrl('images/photo.jpg', 3600);
console.log(url); // 可访问的临时链接

获取文件 URL

const url = await ossClient.getUrl(path: string)

参数:

  • path - 文件路径

示例:

const url = await ossClient.getUrl('images/photo.jpg');
console.log(url); // 文件访问 URL

复制文件

const destPath = await ossClient.copy(sourcePath: string, destPath: string)

参数:

  • sourcePath - 源文件路径
  • destPath - 目标文件路径

示例:

const result = await ossClient.copy(
  'images/photo.jpg',
  'images/photo-backup.jpg',
);
console.log(result); // 复制成功后的目标路径

移动文件

await ossClient.move(sourcePath: string, destPath: string)

参数:

  • sourcePath - 源文件路径
  • destPath - 目标文件路径

示例:

await ossClient.move('images/photo.jpg', 'images/old/photo.jpg');

获取文件大小

const size = await ossClient.getFileSize(path: string)

参数:

  • path - 文件路径

示例:

const size = await ossClient.getFileSize('images/photo.jpg');
console.log(size); // 文件大小(字节)

分片上传相关方法

初始化分片上传
const uploadInfo = await ossClient.initiateMultipartUpload(path: string, partSize?: number)

参数:

  • path - 文件路径
  • partSize - 分片大小 (可选)

示例:

const uploadInfo = await ossClient.initiateMultipartUpload('videos/large.mp4');
上传单个分片
const partInfo = await ossClient.uploadPart(uploadInfo: MultipartUploadInfo, partNumber: number, data: Buffer, start: number, end: number)

示例:

const partInfo = await ossClient.uploadPart(
  uploadInfo,
  1,
  fileBuffer,
  0,
  1024 * 1024,
);
完成分片上传
const result = await ossClient.completeMultipartUpload(uploadInfo: MultipartUploadInfo, parts: PartInfo[])

示例:

const result = await ossClient.completeMultipartUpload(uploadInfo, parts);
取消分片上传
await ossClient.abortMultipartUpload(uploadInfo: MultipartUploadInfo)

示例:

await ossClient.abortMultipartUpload(uploadInfo);
列出已上传的分片
const parts = await ossClient.listParts(uploadInfo: MultipartUploadInfo)

示例:

const parts = await ossClient.listParts(uploadInfo);
断点续传
const result = await ossClient.resumeUpload(options: ResumeUploadOptions)

示例:

const result = await ossClient.resumeUpload({
  path: 'videos/large.mp4',
  file: fs.readFileSync('./large.mp4'),
  progressCallback: (progress) => {
    console.log(`Upload progress: ${progress.percent}%`);
  },
});

批量操作

批量上传
const results = await ossClient.batchUpload(files: Array<{ path: string; file: Buffer | string }>)

示例:

const results = await ossClient.batchUpload([
  { path: 'images/1.jpg', file: fs.readFileSync('./1.jpg') },
  { path: 'images/2.jpg', file: fs.readFileSync('./2.jpg') },
]);
批量删除
await ossClient.batchDelete(paths: string[])

示例:

await ossClient.batchDelete(['images/1.jpg', 'images/2.jpg']);

高级功能扩展

事件监听器

OSSClient 内置了事件监听功能,可以直接使用 onoffemit 方法来管理事件。

import { OSSClient,UploadOptions } from 'luoyu-oss-unified';

class EnhancedOSSClient extends OSSClient {
  async uploadWithEvents(options: UploadOptions) {
    this.emit('upload:start', options);
    try {
      const result = await super.upload(options);
      this.emit('upload:complete', result);
      return result;
    } catch (error) {
      this.emit('upload:error', error);
      throw error;
    }
  }
}
// 创建客户端
const ossClient = new EnhancedOSSClient(minioConfig);

// 监听上传开始事件
ossClient.on('upload:start', (options) => {
  console.log('上传开始:', options.path);
});

// 监听上传进度事件
ossClient.on('upload:progress', (progress) => {
  console.log(`上传进度: ${progress.percent}%`);
});

// 监听上传完成事件
ossClient.on('upload:complete', (result) => {
  console.log('上传完成:', result);
});

// 监听上传错误事件
ossClient.on('upload:error', (error) => {
  console.error('上传错误:', error);
});

// 执行上传操作
await ossClient.uploadWithEvents({
  path: 'files/document.pdf',
  file: fs.readFileSync('./document.pdf'),
  progressCallback: (progress) => {
    ossClient.emit('upload:progress', progress);
    console.log(`Upload progress: ${progress.percent}%`);
  },
});

// 之后可以取消监听
ossClient.off('upload:progress');

分片上传

对于大文件,推荐使用分片上传:

await ossClient.upload({
  path: 'videos/large-video.mp4',
  file: fs.readFileSync('./large-video.mp4'),
  mode: UploadMode.MULTIPART,
  partSize: 10 * 1024 * 1024, // 10MB 每片
  progressCallback: (progress) => {
    console.log(`Upload progress: ${progress.percent}%`);
  },
});

存在性检查

const exists = await ossClient.exists('images/photo.jpg');
console.log(exists); // true/false

获取文件信息

const fileInfo = await ossClient.head('images/photo.jpg');
if (fileInfo) {
  console.log(fileInfo.size); // 文件大小
  console.log(fileInfo.lastModified); // 最后修改时间
}

支持的提供商

  • MinIO - 高性能对象存储
  • 七牛云 - 国内主流 CDN 服务商
  • 阿里云 OSS - 企业级对象存储服务
  • 腾讯云 COS - 腾讯云对象存储

环境要求

  • Node.js >= 14.0.0
  • TypeScript >= 4.0.0 (可选,但推荐)

完整测试代码示例

import {
  OSSClient,
  OSSConfig,
  OSSProvider,
  UploadMode,
} from 'luoyu-oss-unified';
import fs from 'fs';
import path from 'path';

// MinIO 配置
const minioConfig = {
  provider: OSSProvider.MINIO,
  endpoint: 'http://your-minio-server.com',
  accessKeyId: 'your-access-key',
  accessKeySecret: 'your-secret-key',
  bucket: 'your-bucket',
  region: 'us-east-1',
};

// 七牛云配置
const qiniuConfig: OSSConfig = {
  provider: OSSProvider.QINIU,
  accessKeyId: 'your-access-key',
  accessKeySecret: 'your-secret-key',
  bucket: 'your-bucket',
  region: 'z0',
  domain: 'your-domain.qiniudn.com',
};

// 创建客户端
const ossClient = new OSSClient(minioConfig);

// 上传文件
export async function uploadFile() {
  const filePath = path.join(__dirname, '../upload/file.jpg');
  if (!fs.existsSync(filePath)) {
    throw new Error(`File does not exist: ${filePath}`);
  }

  const result = await ossClient.upload({
    path: 'images/test.jpg',
    file: fs.readFileSync(filePath),
    contentType: 'image/jpeg',
    progressCallback: (progress) => {
      console.log(`Upload progress: ${progress.percent}%`);
    },
  });
  console.log('File uploaded:', result);
}

// 下载文件
export async function downloadFile() {
  const buffer = await ossClient.download({
    path: 'images/test.jpg',
  });
  return buffer;
}

// 列出文件
export async function listFiles() {
  const result = await ossClient.list({
    prefix: 'images/',
    limit: 10,
  });
  console.log('Files:', result.objects);
}

// 列出目录
export async function listDirectories() {
  const dirs = await ossClient.listDirectories('images/');
  console.log('Directories:', dirs);
  return dirs;
}

// 创建目录
export async function createDir() {
  await ossClient.createDirectory('documents/');
}

// 上传大文件
export async function uploadLargeFile() {
  const filePath = path.join(__dirname, '../upload/large-file.mp4');
  if (!fs.existsSync(filePath)) {
    throw new Error(`File does not exist: ${filePath}`);
  }

  const result = await ossClient.upload({
    path: 'videos/large.mp4',
    file: fs.readFileSync(filePath),
    mode: UploadMode.MULTIPART,
    partSize: 10 * 1024 * 1024,
    progressCallback: (progress) => {
      console.log(`Upload progress: ${progress.percent}%`);
    },
  });
  console.log('Large file uploaded:', result);
}

// 获取签名 URL
export async function getPresignedUrl() {
  const url = await ossClient.getSignedUrl('images/test.jpg', 3600);
  console.log('Presigned URL:', url);
}

// 批量操作
export async function batchOperations() {
  const uploadResults = await ossClient.batchUpload([
    {
      path: 'images/1.jpg',
      file: fs.readFileSync(path.join(__dirname, '../upload/image1.jpg')),
    },
    {
      path: 'images/2.jpg',
      file: fs.readFileSync(path.join(__dirname, '../upload/image2.jpg')),
    },
  ]);
  console.log('Upload results:', uploadResults);

  // 批量删除
  await ossClient.batchDelete(['images/1.jpg', 'images/2.jpg']);
}

// 复制和移动文件
export async function copyAndMoveFiles() {
  // 复制文件
  const copyResult = await ossClient.copy(
    'images/test.jpg',
    'images/test-copy.jpg',
  );
  console.log('Copy result:', copyResult);

  // 移动文件
  await ossClient.move('images/test-copy.jpg', 'images/backup/test-copy.jpg');
}

// 获取文件信息
export async function getFileInformation() {
  // 获取文件大小
  const size = await ossClient.getFileSize('images/test.jpg');
  console.log('File size:', size);

  // 获取文件URL
  const url = await ossClient.getUrl('images/test.jpg');
  console.log('File URL:', url);

  // 获取签名URL
  const signedUrl = await ossClient.getSignedUrl('images/test.jpg', 3600);
  console.log('Signed URL:', signedUrl);
}

// 目录操作
export async function directoryOperations() {
  // 创建目录
  await ossClient.createDirectory('test/');

  // 列出目录
  const dirs = await ossClient.listDirectories('');
  console.log('Directories:', dirs);

  // 删除目录
  await ossClient.deleteDirectory('test/');
}

贡献

欢迎提交 Issue 和 Pull Request!

许可证

MIT License