Nestjs 使用 fastify-multipart上传文件

1,539 阅读4分钟

最近使用nest来写后端接口,遇到文件上传问题。使用内置的express-multer功能好好的,换了之后,开始不好使了,网上搜索了一圈也没多少资料,调试了好久。手贱 换什么fastify。

Nest.js

Nest.js 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的现代、基于 TypeScript 的框架。它结合了经典的 Node.js 开发风格和面向对象的编程概念,提供了一种优雅且功能强大的方式来构建服务器端应用。

一些 Nest.js 的特点和优势包括:

  1. 基于 TypeScript: Nest.js 是基于 TypeScript 构建的,提供了静态类型检查、面向对象编程等特性,使得代码更具可维护性和可读性。

  2. 模块化架构: Nest.js 使用模块化的架构,允许开发者将应用程序拆分为多个模块,每个模块负责特定的功能或领域,提高了代码的组织性和可重用性。

  3. 依赖注入: Nest.js 内置了依赖注入容器,使得在应用中轻松管理组件之间的依赖关系,提供了更好的可测试性和可扩展性。

  4. 强大的路由系统: Nest.js 提供了强大而灵活的路由系统,支持各种 HTTP 请求方法、路由参数、中间件等,使得定义和管理路由变得简单。

  5. 中间件支持: Nest.js 支持使用中间件来处理请求和响应,可以轻松地添加全局中间件或路由特定中间件来实现各种功能。

  6. 数据库集成: Nest.js 提供了丰富的数据库集成选项,支持各种数据库(如 MySQL、MongoDB、PostgreSQL 等),并提供了模块化的方式来连接和操作数据库。

  7. 社区支持和文档丰富: Nest.js 拥有活跃的社区支持和丰富的文档,使得开发者可以快速上手并解决问题。

Fastify和Express的区别

Fastify是一个高性能的Node.js框架,它是基于Express的,但是比Express更快。Fastify的设计目标是提供一个快速的框架,同时保持易用性和低开销。Fastify的设计是基于插件的,这意味着你可以轻松地扩展Fastify的功能,而不需要修改核心代码。Fastify还提供了一些内置的插件,比如路由、请求验证、日志等。

要在 Nest.js 中使用 Fastify 和 fastify-multipart 插件来处理文件上传,您需要按照以下步骤进行操作:

fastify-multipart

  1. 安装 fastify-multipart 插件:

    • 首先,您需要安装 fastify-multipart 插件。在终端中运行以下命令来安装:
    npm i @fastify/multipart
    
    • fastify-multipart官方使用方法
     const fastify = require('fastify')()
     const fs = require('node:fs')
     const util = require('node:util')
     const { pipeline } = require('node:stream')
     const pump = util.promisify(pipeline)
    
     fastify.register(require('@fastify/multipart'))
    
     fastify.post('/', async function (req, reply) {
       // process a single file
       // also, consider that if you allow to upload multiple files
       // you must consume all files otherwise the promise will never fulfill
       const data = await req.file()
    
       data.file // stream
       data.fields // other parsed parts
       data.fieldname
       data.filename
       data.encoding
       data.mimetype
    
       // to accumulate the file in memory! Be careful!
       //
       // await data.toBuffer() // Buffer
       //
       // or
    
       await pump(data.file, fs.createWriteStream(data.filename))
    
       // be careful of permission issues on disk and not overwrite
       // sensitive files that could cause security risks
    
       // also, consider that if the file stream is not consumed, the promise will never fulfill
    
       reply.send()
     })
    
     fastify.listen({ port: 3000 }, err => {
       if (err) throw err
       console.log(`server listening on ${fastify.server.address().port}`)
     })
    
  2. main.ts 中注册 Fastify 适配器和 fastify-multipart 插件:

    • 在 Nest.js 应用的入口文件 main.ts 中,使用 Fastify 适配器创建应用程序,并注册 fastify-multipart 插件。示例代码如下:
    import { NestFactory } from '@nestjs/core';
    import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
    import * as fastifyMultipart from '@fastify/multipart';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create<NestFastifyApplication>(AppModule, new FastifyAdapter());
    
      // 注册 fastify-multipart 插件
      app.register(fastifyMultipart);
    
      await app.listen(3000);
    }
    bootstrap();
    
  3. 在控制器中处理文件上传:

    • 在您的控制器中编写处理文件上传的方法,并使用 Fastify 的方式来处理文件对象。以下是一个示例代码:
    import { Controller, Post, UploadedFile } from '@nestjs/common';
    import { FastifyRequest } from 'fastify';
    
    @Controller('files')
    export class FilesController {
      
      @Post('upload')
      async uploadFile(@UploadedFile() file: any, @Req() req: FastifyRequest) {
        // 处理文件上传逻辑
         const data = await req.file();
        // 进行文件保存等操作
         let random = Math.random().toString(36).slice(2);
         const filename = `${random}${data.filename.slice(data.filename.lastIndexOf('.'))}`;
         await pump(data.file, createWriteStream(`./uploadimg/${filename}`));
         return 'ok';
       
      }
    }
    
  4. 前端发送文件上传请求:

    • 在前端应用中,通过发送带有文件的 multipart/form-data 请求来上传文件。确保前端发送的请求能够正确匹配后端的路由,并包含所需的文件数据。

在调试的时候我试图直接打印formData对象,然后得到的undefined。郁闷了我好久,后来才发现添加数据是append,获取数据使用的是get方法。

通过以上步骤,您可以在 Nest.js 中使用 Fastify 和 fastify-multipart 插件来处理文件上传。在处理文件上传时,您可以通过 Fastify 的方式来获取文件对象并进行相应的处理。

@fastify/multipart、fastify-multer、nest-fastify-multer

在 Node.js 和 Nest.js 中处理文件上传时,存在几种常用的方式和工具,包括 @fastify/multipartfastify-multernest-fastify-multer。这三个库看起来挺类似的,大家使用和搜索的时候别看岔了文档。这些工具之间有一些区别和特点:

  1. @fastify/multipart:

    • @fastify/multipart 是 Fastify 框架的官方插件,用于处理 multipart/form-data 类型的请求,包括文件上传。它提供了一种简单而有效的方式来处理文件上传,同时与 Fastify 框架无缝集成。
  2. fastify-multer:

    • fastify-multer 是基于 Multer 的 Fastify 插件,用于处理文件上传。Multer 是一个流行的 Node.js 中间件,用于处理 multipart/form-data 类型的请求,并支持文件上传。fastify-multer 将 Multer 整合到 Fastify 框架中,使得在 Fastify 应用中处理文件上传变得更加方便。
  3. nest-fastify-multer:

    • nest-fastify-multer 是 Nest.js 中对 Fastify 的 Multer 中间件的封装。它提供了在 Nest.js 应用中处理文件上传的功能,并与 Fastify 框架集成。通过使用 nest-fastify-multer,您可以在 Nest.js 应用中轻松处理文件上传,而无需直接与 Fastify 或 Multer 进行交互。

这三种工具都是用于处理文件上传的插件或中间件,它们各自在不同框架或环境下提供了方便的文件上传功能。

参考文档