likes
comments
collection
share

Nest 实现文件上传的功能

作者站长头像
站长
· 阅读数 18

我正在参加「掘金·启航计划」

文件上传是 Web 应用程序中常见的功能之一。Nest.js 底层的 HTTP 框架是 Express,它拥有众多强大的中间件来实现各种功能。

本文将介绍如何在 Nest.js 中借助 multer 中间件来实现文件上传的功能。

multer 中间件

Multer 中间件由 Express 团队出品,专门用来处理文件上传,它与 Express 框架紧密集成,在 Nest.js 中基本上也是使用 multer 来完成文件上传的功能。

Multer 的用法非常简单,只需要简单的几行配置,就能实现文件上传的常见需求,比如限制文件类型,大小,同时支持多文件上传。

Multer 是通过解析请求的 multipart/form-data 数据,从中提取文件并将其保存到指定位置或存储系统中。它支持多种存储方式,例如本地磁盘、云存储服务等。

初始化项目

首先使用 Nest CLI 创建项目:

$ nest new nest-upload

然后进入到项目目录,安装下需要的依赖:

$ pnpm add multer
$ pnpm add -D @types/multer

@types/multer 是 multer 中间件模块的类型声明包,可以提供获更好的类型安全。

它提供了一个 Express.Multer.File 类型,表示上传的文件。

配置 Multer 中间件

从内置的 @nestjs/platform-express 导入 MulterModule 模块,它提供的 register 方法可接收一系列的选项,来完成 multer 中间件的配置。

// app.module.ts

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { MulterModule } from '@nestjs/platform-express';
import { diskStorage } from 'multer';
import * as path from 'path';

@Module({
  imports: [
    MulterModule.register({
      storage: diskStorage({
        // 指定文件存储目录
        destination: path.join(__dirname, '../uploads'),
        // 通过时间戳来重命名上传的文件名
        filename: (_, file, callback) => {
          const fileName = `${
            new Date().getTime() + path.extname(file.originalname)
          }`;
          return callback(null, fileName);
        },
      }),
    }),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

文件上传控制器

在 app.controller.ts 中,添加一个处理文件上传请求的控制器方法,使用 @Post 装饰器指定处理 POST 请求的方法,使用 @UseInterceptors@FileInterceptor 装饰器来处理文件上传。FileInterceptor 使用名称为 'file' 的字段来接收上传的文件。

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

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post('upload')
  @UseInterceptors(FileInterceptor('file'))
  async uploadFile(
    @UploadedFile() file: Express.Multer.File,
  ): Promise<{ url: string }> {
    const fileUrl = await this.appService.uploadFile(file);
    return { url: fileUrl };
  }
}

该控制器方法最终返回一个包含文件 Url 的对象,响应给客户端。客户端可以通过这个 URL 去访问文件资源。

创建文件上传的服务

在 app.service.ts 中创建一个服务来处理文件上传的逻辑。

import { Injectable } from '@nestjs/common';
import { MulterDiskUploadedFiles } from '@nestjs/platform-express';
import * as path from 'path';

@Injectable()
export class FileUploadService {
  async uploadFile(file: Express.Multer.File): Promise<string> {
    // 到这里其实文件已经上传到服务器本地了,需要有后续的存储需求,比如要上传到云存储服务中,可以在这里继续处理

    // 返回文件URL
    return `http://localhost/uploads/${file.filename}`;
  }
}

测试接口

使用 ApiPost 等工具来测试一下接口,通过发送 POST 请求到 /upload 路由来测试文件上传功能。使用一个名为 'file' 的文件字段,来包含要上传的文件。

Nest 实现文件上传的功能

打开本地项目的根目录,确实有一个 uploads 目录,里面存放了刚刚上传的文件:

Nest 实现文件上传的功能

小结

本文简单介绍了如何在 Nest 中借助 multer 中间件来完成文件上传的功能,实现非常简单,multer 还支持多文件上传,自定义存储器等好用的功能,大家可以尝试一下。