一文带你弄懂nest.js文件上传

简介: 一文带你弄懂nest.js文件上传

环境配置

为了处理理文件上传,Nest 提供了一个基于 Express 的 multer 中间件包的内置模块。Multer 处理以该格式发布的数据,主要用于通过 HTTP 请求上传文件。此模块是完全可配置的。


所需依赖包如下:


pnpm add multer
pnpm add -D @types/multer

上传配置可以放在控制器方法,也可以放在模块中,下面是在模块中定义。


模块配置

首先创建一个crud模板


在upload.module.ts模块中引入这些配置

import { Global, Module } from '@nestjs/common'
import { MulterModule } from '@nestjs/platform-express'
import { diskStorage } from 'multer'
import { extname } from 'path'
import { UploadController } from './upload.controller'
import { UploadService } from './upload.service'
@Global()
@Module({
  imports: [
    MulterModule.registerAsync({
      useFactory() {
        return {
          storage: diskStorage({
            //文件储存位置
            destination: 'uploads',
            //文件名定制
            filename: (req, file, callback) => {
              const path = Date.now() + '-' + Math.round(Math.random() * 1e10) + extname(file.originalname)
              callback(null, path)
            },
          }),
        }
      },
    }),
  ],
  controllers: [UploadController],
  providers: [UploadService]
})
export class UploadModule { }


这里我们是在upload模块中注册了MulterModule模块,异步注册后,通过工厂函数的方式对上传的文件进行了定制化配置,这里的格式是日期+随机数+文件拓展名的方式


controller使用

接着在控制器中使用,要上传单个文件,只需将拦截器绑定到路由处理程序,然后使用装饰器从中提取。拦截器后面再具体讲解,它其实就是在访问路由前后对数据进行的处理。


image.png

import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
@Controller('upload')
export class UploadController {
  @Post('image')
  @UseInterceptors(FileInterceptor('file'))
  image(@UploadedFile() file: Express.Multer.File) {
    return file
  }
}

我们可以测试一下,能够得到文件的具体信息


image.png


FileInterceptor配置

我们这里用到的拦截器FileInterceptor()它有两个参数


fileName: 提供保存文件的 HTML 表单中的字段名称的字符串


options: 类型的可选对象,与 multer 构造函数使用的对象相同,主要可以配置上传文件的大小之类的


我们给展开写写看看


import { Controller, MethodNotAllowedException, Post, UploadedFile, UseInterceptors } from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
@Controller('upload')
export class UploadController {
  @Post('upload')
  @UseInterceptors(FileInterceptor('file', {
    limits: { fileSize: Math.pow(1024, 2) * 2 },
    fileFilter(req: any, file: Express.Multer.File, callback: (error: Error | null, acceptFile: boolean) => void) {
      if (!file.mimetype.includes('image')) {
        callback(new MethodNotAllowedException('类型不支持'), false)
      } else {
        callback(null, true)
      }
    }
  }))
  image(@UploadedFile() file: Express.Multer.File) {
    return file
  }
}


里面的配置项,第一个是限制文件大小,第二个是一个函数,用来限制文件类型的


limits: 对文件大小,文件名大小等限制

fileFilter()对文件类型验证的函数

 filterFile接受三个参数:


req:请求对象

file: 上传的文件,进行类型判断的

callback: 回调函数,用于返回验证结果 第一个参数位null或者error 第二个参数acceptFile 一个布尔值 。

当上传的文件类型满足有image时返回null,acceptFile返回true


否则返回一个error以及false


当我上传一个不是图片类型(jpg png webp gif jpeg等)的文件时 会报类型错误


image.png


如果上传分图片/文档等不同类型的上传处理,使用上面的方式需要在控制器的不同方法定义重复度很高的代码 。下面我们来简化这个过程。


优化代码

聚合装饰器

我们将 @UseInterceptors(FileInterceptor('file')) 通过装饰器聚合来简化代码,下面在 ./upload.ts 文件中定义。


image.png


import { applyDecorators, UseInterceptors } from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface'
export function upload(fieldName = 'file', options: MulterOptions = {}) {
  return applyDecorators(UseInterceptors(FileInterceptor(fieldName, options)))
}

这样在controller中可以这样直接用@upload就可以将之前那一堆东西简化


image.png

抽离代码封装

在./upload.ts中将fileFilter封装起来让上传的文件类型更加灵活


import { applyDecorators, UnsupportedMediaTypeException, UseInterceptors } from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { MulterOptions } from '@nestjs/platform-express/multer/interfaces/multer-options.interface'
export function upload(fieldName = 'file', options: MulterOptions = {}) {
    return applyDecorators(UseInterceptors(FileInterceptor(fieldName, options)))
}
export function fileMimetypeFilter(...mimes: string[]) {
    return (req: any, file: Express.Multer.File, callback: (error: Error | null, acceptFile: boolean) => void) => {
        if (mimes.some(mime => file.mimetype.includes(mime))) {
            callback(null, true)
        } else {
            callback(new UnsupportedMediaTypeException('文件类型错误'), false)
        }
    }
}


在controller中使用


image.png


到这里基本已经结束了,但是对代码封装的更深一点,我们可以对每种上传的文件进行一次封装


image.png


在controller中使用  这样一看是不是代码简洁多了

image.png

写在最后

nest.js的文件乍一看确实吓人,配置文件很多,学知识就像谈恋爱,要慢慢来,多看文档,多敲代码 官方文档很给力,希望能够帮助到大家!

相关文章
快速入门nest.js(7/10)--应用配置
然后,你就可以像下面的方式使用对应的变量值了,注意这里所有的变量值都是字符串,而port要求的是数字,所以我们还需要进行一个转换。
129 0
|
9月前
|
前端开发
前端学习笔记202306学习笔记第三十五天-js-js中内置的类1
前端学习笔记202306学习笔记第三十五天-js-js中内置的类1
28 0
|
9月前
|
前端开发
前端学习笔记202306学习笔记第三十五天-js-js中内置的类2
前端学习笔记202306学习笔记第三十五天-js-js中内置的类2
25 0
|
10月前
|
JSON 前端开发 JavaScript
NEST.JS使用心得
NEST.JS使用心得
|
缓存 JavaScript 安全
快速入门nest.js(6/10)--原理细节
依赖注入 我们将依赖的实例委托给IOC容器,在这里,这个IOC容器就是NestJS运行时系统本身,NestJS在这里处理所有繁重的工作,而不是尝试自己实现依赖注入。本质上,当我们“ask”类构造函数中的依赖项时,NestJS处理并检索返回给我们的对象,以及它可能需要的任何依赖项等等。
169 0
|
存储 关系型数据库 测试技术
快速入门nest.js(10/10)--测试
初识Jest 很好的错误消息和内置Mocking实用程序 可靠的并行运行测试 优先运行以前失败的测试 根据测试文件花费的时间重新组织测试运行
267 0
|
JavaScript 前端开发
Nest.js学习笔记(七)
本节详细介绍Nest.js的控制器,以及使用Apifox做了简单的测试
234 0
|
前端开发
Nest.js学习笔记(九)
本节记录Nest.js提供者相关的内容
117 0
|
API
Nest.js学习笔记(六)
本节记录Restful风格Api的介绍以及使用Nest.js做了一个简单的版本控制
117 0
|
容器
Nest.js学习笔记(二)
本节记录依赖倒置、控制反转、依赖注入相关内容
60 0