New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@meta-1/nest-assets

Package Overview
Dependencies
Maintainers
1
Versions
10
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@meta-1/nest-assets

NestJS assets module for S3 and OSS object storage

latest
npmnpm
Version
0.0.11
Version published
Maintainers
1
Created
Source

@meta-1/nest-assets

NestJS 资源管理模块,支持亚马逊 S3、阿里云 OSS 和 MinIO 对象存储。

功能特性

  • ✅ 支持亚马逊 S3、阿里云 OSS 和 MinIO
  • ✅ 预签名 URL 模式,客户端直传
  • ✅ 统一接口,内部自动切换存储提供商
  • ✅ 支持私桶和公桶
  • ✅ 私桶访问自动签名授权
  • ✅ 可配置签名有效期

安装

npm install @meta-1/nest-assets

所有必需的依赖(包括 AWS S3 SDK、阿里云 OSS SDK 和 MinIO SDK)会自动安装。

使用方法

1. 导入并配置模块

import { Module } from '@nestjs/common';
import { AssetsModule } from '@meta-1/nest-assets';
import { StorageProvider } from '@meta-1/nest-types';

@Module({
  imports: [
    // 使用 S3
    AssetsModule.forRoot({
      storage: {
        provider: StorageProvider.S3,
        publicBucket: 'my-public-bucket',
        privateBucket: 'my-private-bucket',
        expiresIn: '30m'  // 支持字符串(如 '30m', '1h', '2d')或数字(毫秒)
      },
      s3: {
        region: 'us-east-1',
        accessKeyId: 'your-access-key-id',
        secretAccessKey: 'your-secret-access-key',
        endpoint: 'https://s3.amazonaws.com'  // 可选,用于兼容 S3 的服务
      }
    }),
    
    // 或使用阿里云 OSS
    AssetsModule.forRoot({
      storage: {
        provider: StorageProvider.OSS,
        publicBucket: 'my-public-bucket',
        privateBucket: 'my-private-bucket',
        expiresIn: '30m'
      },
      oss: {
        region: 'oss-cn-hangzhou',
        accessKeyId: 'your-access-key-id',
        accessKeySecret: 'your-secret-access-key'
      }
    }),
    
    // 或使用 MinIO
    AssetsModule.forRoot({
      storage: {
        provider: StorageProvider.MINIO,
        publicBucket: 'my-public-bucket',
        privateBucket: 'my-private-bucket',
        expiresIn: '30m'
      },
      minio: {
        endpoint: 'http://localhost:9000',  // 支持 http://host:port 或 https://host:port 格式
        accessKeyId: 'your-access-key-id',
        secretAccessKey: 'your-secret-access-key',
        useSSL: false,  // 可选,默认 false。也可以通过 endpoint 的协议自动推断
        region: 'us-east-1'  // 可选,默认 'us-east-1'
      }
    })
  ]
})
export class AppModule {}

2. 从配置文件加载

// main.ts
import { NestFactory } from '@nestjs/core';
import { ConfigLoader, ConfigSourceType } from '@meta-1/nest-common';

interface AppConfig {
  assets: AssetsConfig;
}

async function bootstrap() {
  // 加载配置
  const loader = new ConfigLoader<AppConfig>({
    type: ConfigSourceType.LOCAL_YAML,
    filePath: './config/app.yaml'
  });
  
  const config = await loader.load();
  
  // 创建模块
  @Module({
    imports: [AssetsModule.forRoot(config.assets)]
  })
  class AppModule {}
  
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

配置文件示例 (config/app.yaml):

assets:
  storage:
    provider: s3  # 's3' | 'oss' | 'minio'
    publicBucket: my-public-bucket
    privateBucket: my-private-bucket
    expiresIn: 30m
  s3:
    region: us-east-1
    accessKeyId: ${AWS_ACCESS_KEY_ID}
    secretAccessKey: ${AWS_SECRET_ACCESS_KEY}
    endpoint: ${AWS_S3_ENDPOINT}  # 可选
  oss:
    region: oss-cn-hangzhou
    accessKeyId: ${ALIYUN_ACCESS_KEY_ID}
    accessKeySecret: ${ALIYUN_ACCESS_KEY_SECRET}
  minio:
    endpoint: ${MINIO_ENDPOINT}  # 支持 http://host:port 或 https://host:port 格式
    accessKeyId: ${MINIO_ACCESS_KEY_ID}
    secretAccessKey: ${MINIO_SECRET_ACCESS_KEY}
    useSSL: false  # 可选,默认 false
    region: us-east-1  # 可选,默认 'us-east-1'

3. 在业务方创建 Controller

重要: AssetsModule 只提供 Service,Controller 需要由业务方实现。这样可以添加权限控制、日志等业务逻辑。

// src/controllers/assets.controller.ts
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiBearerAuth } from '@nestjs/swagger';
import { JwtAuthGuard } from '@/guards/jwt-auth.guard';
import {
  AssetsService,
  PresignedUploadUrlRequest,
  PresignedUploadUrlResponse,
  PresignedDownloadUrlRequest,
  PresignedDownloadUrlResponse,
} from '@meta-1/nest-assets';

@ApiTags('Assets')
@Controller('api/assets')
@UseGuards(JwtAuthGuard)  // ✅ 添加权限验证
@ApiBearerAuth()
export class AssetsController {
  constructor(private readonly assetsService: AssetsService) {}

  @Post('presigned-upload-url')
  @ApiOperation({ summary: '生成预签名上传 URL' })
  async generatePresignedUploadUrl(
    @Body() request: PresignedUploadUrlRequest
  ): Promise<PresignedUploadUrlResponse> {
    return this.assetsService.generatePresignedUploadUrl(request);
  }

  @Post('presigned-download-url')
  @ApiOperation({ summary: '生成预签名下载 URL' })
  async generatePresignedDownloadUrl(
    @Body() request: PresignedDownloadUrlRequest
  ): Promise<PresignedDownloadUrlResponse> {
    return this.assetsService.generatePresignedDownloadUrl(request);
  }
}

然后在 AppModule 中注册:

@Module({
  imports: [AssetsModule],
  controllers: [AssetsController],  // ✅ 注册业务方的 Controller
})
export class AppModule {}

更多示例: 查看 CONTROLLER_EXAMPLE.md 了解如何添加权限控制、日志、限流等功能。

4. 在业务代码中使用服务

import { Injectable } from '@nestjs/common';
import { AssetsService, BucketType } from '@meta-1/nest-assets';

@Injectable()
export class MyService {
  constructor(private readonly assetsService: AssetsService) {}

  async uploadFile() {
    // 生成预签名上传 URL
    const uploadUrl = await this.assetsService.generatePresignedUploadUrl({
      fileName: 'example.jpg',
      contentType: 'image/jpeg',
      bucketType: BucketType.PUBLIC,  // 或 BucketType.PRIVATE
      prefix: 'images',  // 可选,文件路径前缀
    });

    // 返回给客户端
    return {
      uploadUrl: uploadUrl.uploadUrl,  // 客户端用此 URL 上传文件
      fileUrl: uploadUrl.fileUrl,      // 上传成功后的访问地址
      fileKey: uploadUrl.fileKey,      // 文件唯一标识
      expiresAt: uploadUrl.expiresAt,  // 过期时间
    };
  }

  async downloadFile(fileUrl: string) {
    // 生成预签名下载 URL
    // 如果是公桶,直接返回原 URL
    // 如果是私桶,返回带签名的临时 URL
    const downloadUrl = await this.assetsService.generatePresignedDownloadUrl({
      url: fileUrl,
    });

    return downloadUrl;
  }
}

5. API 请求示例

使用内置的 Controller:

# 生成上传 URL
POST /assets/presigned-upload-url
Content-Type: application/json

{
  "fileName": "example.jpg",
  "contentType": "image/jpeg",
  "bucketType": "public",
  "prefix": "images"
}

# 生成下载 URL
POST /assets/presigned-download-url
Content-Type: application/json

{
  "url": "http://meta1top:30900/wiki-private/1234567890_abc_example.jpg"
}

注意: 所有请求参数都会自动进行类型验证,Swagger UI 会显示完整的 Schema 信息。

客户端上传示例

// 1. 获取预签名上传 URL
const { uploadUrl, fileUrl } = await fetch('/assets/presigned-upload-url', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    fileName: 'example.jpg',
    contentType: 'image/jpeg',
    bucketType: 'public',
  }),
}).then(res => res.json());

// 2. 使用预签名 URL 上传文件
await fetch(uploadUrl, {
  method: 'PUT',
  headers: { 'Content-Type': 'image/jpeg' },
  body: fileBlob,
});

// 3. 上传成功后,使用 fileUrl 访问文件
console.log('文件地址:', fileUrl);

桶类型说明

模块支持两种桶类型,通过 BucketType 枚举指定,系统会自动将文件存储到对应的桶中:

  • 公桶 (BucketType.PUBLIC):

    • 文件存储到 storage.publicBucket 配置的桶中
    • 上传需要签名
    • 访问不需要签名,可直接访问
    • 适用于公开资源(如网站图片、文档等)
  • 私桶 (BucketType.PRIVATE):

    • 文件存储到 storage.privateBucket 配置的桶中
    • 上传需要签名
    • 访问需要签名,有时效性
    • 适用于私密资源(如用户私人文件、敏感数据等)

配置示例

assets:
  storage:
    provider: s3
    publicBucket: my-public-bucket    # 公共文件存储桶
    privateBucket: my-private-bucket  # 私密文件存储桶
    expiresIn: 30m

当调用 API 时指定 bucketType: "public"bucketType: "private",文件会自动存储到对应的桶中。

API 参考

AssetsService

generatePresignedUploadUrl(request)

生成预签名上传 URL。

参数:

  • fileName: 文件名
  • contentType: 文件 MIME 类型
  • bucketType: 桶类型 (BucketType.PUBLIC | BucketType.PRIVATE)
  • prefix: 可选,文件路径前缀

返回:

  • uploadUrl: 预签名上传 URL
  • fileUrl: 文件访问 URL(公桶可直接访问,私桶需要通过预签名下载 URL 访问)
  • fileKey: 文件唯一标识
  • expiresAt: 过期时间(Unix 时间戳)

generatePresignedDownloadUrl(request)

生成预签名下载 URL。会自动判断是公桶还是私桶:

  • 公桶:直接返回原 URL(不过期)
  • 私桶:返回带签名的临时 URL(有过期时间)

参数:

  • url: 文件完整 URL(从上传接口返回的 url 字段)

返回:

  • downloadUrl: 下载 URL(公桶返回原 URL,私桶返回预签名 URL)
  • expiresAt: 过期时间(0 表示不过期,仅公桶)

许可证

MIT

Keywords

nestjs

FAQs

Package last updated on 05 Jan 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts