Nestjs高级进阶文件上传处理技巧

在使用NestJS处理文件上传时遇到几个高级问题想请教:1) 如何实现大文件分片上传和断点续传功能?2) 怎样通过Interceptor对上传文件进行统一格式校验和大小限制?3) 有没有优雅的方式处理多文件上传的场景,比如动态字段名和批量验证?4) 如何在文件上传后自动生成缩略图或触发后续处理流程?5) 生产环境中如何将文件高效存储到云服务(如S3/MinIO)并保持代码可测试性?

3 回复

在NestJS中处理文件上传时,可以使用@nestjs/common中的内置模块MulterModule来实现。首先,你需要安装必要的依赖:

npm install @nestjs/platform-express multer

接着,在你的模块中配置Multer

import { Module } from '@nestjs/common';
import { MulterModule } from '@nestjs/platform-express';

@Module({
  imports: [
    MulterModule.register({
      storage: // 配置存储方式,比如硬盘或云存储,
      fileFilter: // 过滤特定类型的文件,
      limits: { fileSize: 1024 * 1024 * 5 } // 设置最大上传大小5MB
    })
  ],
})
export class AppModule {}

然后,在控制器中定义上传接口:

import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('upload')
export class UploadController {
  @Post()
  @UseInterceptors(FileInterceptor('file')) // 绑定文件字段名
  async uploadFile(@UploadedFile() file) {
    return { fileName: file.filename };
  }
}

高级技巧包括:结合AWS S3等云存储服务,通过自定义存储适配器实现更复杂的文件管理逻辑,以及对上传的文件进行预处理和后处理。同时,记得在生产环境中对文件类型、大小等进行严格校验以防止安全漏洞。


作为一个屌丝程序员,分享一些NestJS中文件上传的实用技巧:

  1. 使用Multer模块:NestJS推荐使用Multer来处理文件上传。先安装[@nestjs](/user/nestjs)/platform-expressmulter,然后创建一个上传中间件,例如:

    import { MulterOptions } from '[@nestjs](/user/nestjs)/platform-express';
    import { diskStorage } from 'multer';
    
    export const multerOptions: MulterOptions = {
      storage: diskStorage({
        destination: './uploads',
        filename: (req, file, cb) => {
          const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
          const ext = file.mimetype.split('/')[1];
          cb(null, `${file.fieldname}-${uniqueSuffix}.${ext}`);
        },
      }),
    };
    
  2. 控制器设计:在控制器中注入上传配置,例如:

    [@Post](/user/Post)('upload')
    [@UseInterceptors](/user/UseInterceptors)(FileInterceptor('file', multerOptions))
    uploadFile([@UploadedFile](/user/UploadedFile)() file: Express.Multer.File) {
      return { url: file.path };
    }
    
  3. 文件类型限制:通过设置fileFilter进一步限制上传文件的类型,例如只允许上传图片:

    fileFilter: (req, file, cb) => {
      if (file.mimetype.match(/\/(jpg|jpeg|png|gif)$/)) {
        cb(null, true);
      } else {
        cb(newHttpException('Only images are allowed!', HttpStatus.BAD_REQUEST), false);
      }
    }
    
  4. 大文件分片上传:对于大文件可以结合前端分片上传工具如axios-blob,后端则需要接收分片并合并。

  5. 存储优化:可以将文件存储到云服务(如阿里云OSS、AWS S3),而非本地磁盘,提升性能和扩展性。

NestJS高级文件上传处理技巧

在NestJS中处理文件上传有几个高级技巧可以提升应用的性能和安全性:

1. 使用Multer中间件优化配置

import { diskStorage } from 'multer';
import { extname } from 'path';

const storage = diskStorage({
  destination: './uploads',
  filename: (req, file, callback) => {
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
    const ext = extname(file.originalname);
    callback(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
  },
});

@Post('upload')
@UseInterceptors(
  FileInterceptor('file', {
    storage,
    limits: {
      fileSize: 1024 * 1024 * 5, // 5MB限制
      files: 1, // 限制文件数量
    },
    fileFilter: (req, file, callback) => {
      if (!file.originalname.match(/\.(jpg|jpeg|png|gif)$/)) {
        return callback(new Error('Only image files are allowed!'), false);
      }
      callback(null, true);
    },
  })
)
uploadFile(@UploadedFile() file: Express.Multer.File) {
  return { filename: file.filename };
}

2. 流式处理大文件

对于大文件,可以使用流式处理避免内存问题:

import { createReadStream } from 'fs';
import { pipeline } from 'stream/promises';

@Post('stream-upload')
@UseInterceptors(FileInterceptor('file'))
async streamUpload(@UploadedFile() file: Express.Multer.File) {
  const readStream = createReadStream(file.path);
  const writeStream = createWriteStream(`./processed/${file.filename}`);
  
  await pipeline(readStream, writeStream);
  return { message: 'File processed successfully' };
}

3. 多文件上传处理

@Post('multiple')
@UseInterceptors(FilesInterceptor('files', 5)) // 最多5个文件
uploadMultiple(@UploadedFiles() files: Array<Express.Multer.File>) {
  return files.map(file => ({
    originalname: file.originalname,
    size: file.size,
  }));
}

4. 文件上传到云存储

import { S3 } from 'aws-sdk';

const s3 = new S3({
  accessKeyId: process.env.AWS_ACCESS_KEY,
  secretAccessKey: process.env.AWS_SECRET_KEY,
});

@Post('s3-upload')
@UseInterceptors(FileInterceptor('file'))
async uploadToS3(@UploadedFile() file: Express.Multer.File) {
  const result = await s3.upload({
    Bucket: 'your-bucket-name',
    Key: `uploads/${Date.now()}-${file.originalname}`,
    Body: file.buffer,
  }).promise();
  
  return { location: result.Location };
}

5. 安全考虑

  • 验证文件类型和大小
  • 扫描上传文件中的恶意内容
  • 使用临时目录处理文件
  • 限制上传频率(使用throttler)

这些技巧可以帮助你构建更健壮的文件上传功能。

回到顶部