一文带你弄懂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的文件乍一看确实吓人,配置文件很多,学知识就像谈恋爱,要慢慢来,多看文档,多敲代码 官方文档很给力,希望能够帮助到大家!

相关文章
|
2月前
|
存储 中间件 文件存储
Nest.js 实战 (五):如何实现文件本地上传
这篇文章介绍了使用Nest框架和multer中间件包实现文件上传功能的过程。首先,作者在开发用户管理模块时遇到了需要上传用户头像的需求,因此开发了文件上传功能。文章详细介绍了如何安装依赖,如何处理单个文件上传,如何在模块层注册并配置文件上传路径,并以代码形式展示了如何实现这些功能。最后,作者对使用第三方平台存储文件进行了说明,并建议业务量大的公司很少用上传到服务器本地的方式,该方式更适合个人站点、博客使用。
|
4月前
|
存储 JavaScript 前端开发
js必备知识小结(一)
js必备知识小结(一)
27 0
|
4月前
|
存储 JSON JavaScript
js必备知识小结(二)
js必备知识小结(二)
29 0
|
JavaScript 中间件 关系型数据库
js编程时常见问题解决方法
js编程时常见问题解决方法
js编程时常见问题解决方法
|
前端开发
前端学习笔记202306学习笔记第三十五天-js-js中内置的类1
前端学习笔记202306学习笔记第三十五天-js-js中内置的类1
35 0
|
前端开发
前端学习笔记202306学习笔记第三十五天-js-js中内置的类2
前端学习笔记202306学习笔记第三十五天-js-js中内置的类2
34 0
|
JSON 前端开发 JavaScript
NEST.JS使用心得
NEST.JS使用心得
|
API
Nest.js学习笔记(六)
本节记录Restful风格Api的介绍以及使用Nest.js做了一个简单的版本控制
133 0
|
开发框架 JavaScript 前端开发
Nest.js学习笔记(一)
本系列笔记内容根据B站up主“小满zs”视频教程整理而成,本节简要介绍Nest.js
117 0
|
JavaScript 前端开发
Nest.js学习笔记(七)
本节详细介绍Nest.js的控制器,以及使用Apifox做了简单的测试
264 0