Nestjs教程文件上传与下载功能实现

我正在学习NestJS的文件上传与下载功能,遇到几个问题想请教:

  1. 如何在NestJS中配置multer来处理文件上传?官方文档的示例不太清楚具体配置参数的作用。
  2. 文件上传后如何自定义存储路径和文件名?目前默认是保存在内存中,想改成保存到服务器指定目录。
  3. 实现文件下载功能时,如何设置正确的响应头让浏览器弹出下载对话框?特别是处理不同文件类型时。
  4. 有没有完整的代码示例展示从上传到下载的完整流程?包括前端form表单和后端接口的配合。
  5. 大文件上传时有什么优化方案?比如分片上传或进度条显示的实现。
3 回复

要在NestJS中实现文件上传和下载功能,可以按照以下步骤操作:

  1. 安装依赖:首先,你需要安装必要的模块。使用[@nestjs](/user/nestjs)/common[@nestjs](/user/nestjs)/multer(处理文件上传)和fs(文件系统模块,用于文件下载)。

  2. 配置Multer:在你的模块中配置Multer,设置上传目录和文件名规则。例如:

    import { Module } from '[@nestjs](/user/nestjs)/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import * as multer from 'multer';
    
    const storage = multer.diskStorage({
      destination: function (req, file, cb) {
        cb(null, 'uploads/');
      },
      filename: function (req, file, cb) {
        cb(null, Date.now() + '-' + file.originalname);
      },
    });
    
    [@Module](/user/Module)({
      imports: [],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}
    
  3. 创建控制器:在控制器中定义上传和下载的路由。例如:

    import { Controller, Post, UploadedFile, Res } from '[@nestjs](/user/nestjs)/common';
    import { FileInterceptor } from '[@nestjs](/user/nestjs)/platform-express';
    
    [@Controller](/user/Controller)('files')
    export class FilesController {
      @Post('upload')
      @UseInterceptors(FileInterceptor('file', { storage }))
      uploadFile(@UploadedFile() file) {
        return { filename: file.filename };
      }
    
      @Get('download/:filename')
      downloadFile(@Res() res, @Param('filename') filename: string) {
        res.sendFile(filename, { root: 'uploads/' });
      }
    }
    
  4. 测试功能:运行应用后,可以通过POST请求上传文件,GET请求下载文件。

这样就完成了基本的文件上传和下载功能。记得处理异常和清理上传目录中的旧文件以避免磁盘空间耗尽。


要实现文件上传和下载功能,首先安装@nestjs/common@nestjs/multer以及multer库。创建一个控制器处理上传和下载逻辑。

  1. 上传:配置Multer处理文件上传。在main.ts引入Multer模块并定义存储策略。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MulterModule } from '@nestjs/platform-express';

@Module({
  imports: [
    MulterModule.register({
      storage: diskStorage({
        destination: './uploads',
        filename: (req, file, cb) => {
          const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
          cb(null, file.fieldname + '-' + uniqueSuffix + '.' + extname(file.originalname));
        },
      }),
    }),
  ],
})
export class AppModule {}
  1. 控制器:编写上传和下载接口。
import { Controller, Post, UploadedFile, Res } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { Response } from 'express';

@Controller('files')
export class FilesController {
  @Post('upload')
  @FileInterceptor('file') // 处理文件字段名为file
  async uploadFile(@UploadedFile() file, @Res() res: Response) {
    if (!file) return res.status(400).send('No file uploaded');
    return res.send({ message: 'File uploaded successfully', file });
  }

  @Get('download/:filename')
  async downloadFile(@Res() res: Response, @Param('filename') filename: string) {
    try {
      return res.download(`./uploads/${filename}`);
    } catch (err) {
      return res.status(500).send({ message: 'Error downloading file' });
    }
  }
}

确保上传目录存在,运行项目后可测试上传与下载功能。

NestJS 文件上传与下载功能实现

文件上传实现

  1. 首先安装所需依赖:
npm install @nestjs/platform-express multer
npm install @types/multer -D
  1. 创建一个文件上传模块:
import { Module } from '@nestjs/common';
import { FileController } from './file.controller';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import { extname } from 'path';

@Module({
  imports: [
    MulterModule.register({
      storage: diskStorage({
        destination: './uploads',
        filename: (req, file, callback) => {
          const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
          const ext = extname(file.originalname);
          const filename = `${uniqueSuffix}${ext}`;
          callback(null, filename);
        },
      }),
    }),
  ],
  controllers: [FileController],
})
export class FileModule {}
  1. 创建文件上传控制器:
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';

@Controller('file')
export class FileController {
  @Post('upload')
  @UseInterceptors(FileInterceptor('file'))
  uploadFile(@UploadedFile() file: Express.Multer.File) {
    return {
      originalname: file.originalname,
      filename: file.filename,
      size: file.size,
      mimetype: file.mimetype,
    };
  }
}

文件下载实现

  1. 在文件控制器中添加下载方法:
import { Controller, Get, Param, Res } from '@nestjs/common';
import { Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';

@Controller('file')
export class FileController {
  // ...之前的uploadFile方法...

  @Get('download/:filename')
  downloadFile(@Param('filename') filename: string, @Res() res: Response) {
    const filePath = path.join(__dirname, '../../uploads', filename);
    
    if (fs.existsSync(filePath)) {
      res.download(filePath, filename);
    } else {
      res.status(404).send('File not found');
    }
  }
}

注意事项

  1. 确保你的应用有写入./uploads目录的权限

  2. 在生产环境中,建议:

    • 将上传文件存储在云存储服务中
    • 添加文件类型和大小限制
    • 实现文件清理机制
    • 考虑安全因素,如防止恶意文件上传
  3. 前端调用示例:

// 上传文件
const formData = new FormData();
formData.append('file', fileInput.files[0]);

fetch('/api/file/upload', {
  method: 'POST',
  body: formData
});

// 下载文件
window.open('/api/file/download/filename.ext');
回到顶部