当前位置:网站首页>Nestjs配置文件上传, 配置中间件以及管道的使用
Nestjs配置文件上传, 配置中间件以及管道的使用
2022-07-06 04:43:00 【Johnny丶me】
Nestjs中的文件上传
- 文档: https://docs.nestjs.com/techniques/file-upload
安装插件
- $
yarn add @types/multer
示例
1 ) 简单单个上传
前端代码
<form action="upload/add" method="post" enctype="multipart/form-data"> <input type="file" name="files" /> <br> <br> <input type="submit" value="提交"> </form>
后端代码
import { Controller, Get, Render, Post, Body, UseInterceptors, UploadedFile } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { createWriteStream } from 'fs'; import { join } from 'path'; @Controller('upload') export class UploadController { @Get() @Render('default/upload') index() { } @Post('add') @UseInterceptors(FileInterceptor('files')) doAdd(@Body() body, @UploadedFile() file) { console.log(body); console.log(file); //上传图片的信息 必须在form的属性里面配置enctype="multipart/form-data" const writeStream = createWriteStream(join(__dirname, '../../public/upload', `${ Date.now()}-${ file.originalname}`)) writeStream.write(file.buffer); return '上传图片成功'; } }
2 ) 多文件上传
- 如果field一样(用的name都是files),我们可选择使用 UploadedFiles 的方法来处理,并且通过 for … of 来遍历
- 如果不一样,则提供了,如下的配置
@Post('upload') @UseInterceptors(FileFieldsInterceptor([ { name: 'avatar', maxCount: 1 }, { name: 'background', maxCount: 1 }, ])) uploadFile(@UploadedFiles() files: { avatar?: Express.Multer.File[], background?: Express.Multer.File[] }) { console.log(files); }
- 或者使用Any类型的拦截器AnyFilesInterceptor
@Post('upload') @UseInterceptors(AnyFilesInterceptor()) uploadFile(@UploadedFiles() files: Array<Express.Multer.File>) { console.log(files); }
- 需要注意的是,我们每次上传时,这些路径,图片处理什么的,需要封装一下
Nestjs 中间件
- 同express一样,nestjs中间件也可以理解为在请求和响应之间的一个管道处理程序
- 可以是一个函数,也可以是一个@Injectable() 装饰器装饰的类
中间件作用
- 执行任何代码
- 对请求和响应对象进行更改
- 结束请求-响应周期
- 调用堆栈中的下一个中间件函数
- 如果当前的中间件函数没有结束请求-响应周期, 它必须调用 next() 将控制传递给下一个中间件函数
- 否则, 请求将被挂起
中间件的创建和使用
1 ) 创建
- $
nest g middleware http
这里http是中间件名 - 会生成src/http.middleware.ts文件,如下:
import { Injectable, NestMiddleware } from '@nestjs/common'; @Injectable() export class HttpMiddleware implements NestMiddleware { use(req: any, res: any, next: () => void) { next(); } }
- 我们按照文档上,改造一下
import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response, NextFunction } from 'express'; @Injectable() export class HttpMiddleware implements NestMiddleware { use(req: Request, res: Response, next: NextFunction) { console.log('Request...'); next(); } }
2 ) 在app.module.ts中使用
import {
Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import {
HttpMiddleware } from './http.middleware';
import {
CatsModule } from './cats/cats.module'; // 模块
@Module({
imports: [CatsModule],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(HttpMiddleware)
// .forRoutes('cats'); // 表示哪些路由可以使用这个中间件
// .forRoutes(someController); // 匹配所有的路由 // 或者传入指定控制器,但是不建议这样写
// .forRoutes({path: 'cats', method: RequestMethod.GET}); // 只匹配GET
// .forRoutes({path: 'cats', method: RequestMethod.ALL}); // 匹配所有方法
// .forRoutes({path: 'cats', method: RequestMethod.ALL}, {path: 'user', method: RequestMethod.ALL}); // 配置多个
.forRoutes('*'); // 匹配所有的路由
}
}
- 当然,我们最好把中间件放到一个通用的模块中,如下:./common/middleware/
import { LoggerMiddleware } from './common/middleware/logger.middleware';
- 其实可以在创建的时候指定目录 $
nest g middleware common/middleware/http.middleware
3 ) 配置多个中间件的示例
3.1 一种配置
import {
Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import {
HttpMiddleware } from './http.middleware';
import {
UserMiddleware } from './user.middleware';
@Module({
imports: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(HttpMiddleware).forRoutes('*')
.apply(UserMiddleware).forRoutes('user')
}
}
3.2 另一种配置
// 这里只写关键代码
consumer
.apply(NewsMiddleware,UserMiddleware)
.forRoutes({
path: 'u*r', method: RequestMethod.ALL},{
path: 'news', method: RequestMethod.ALL}) // 这里不讲究顺序
4 ) 函数式中间件
// 只写关键代码
export function logger(req, res, next) {
console.log(`函数式中间件...`);
next();
};
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(HttpMiddleware, logger).forRoutes('*')
}
}
5 ) 全局中间件
在main.ts中使用,注意不能使用类中间件,只能使用函数中间件
//全局中间件只能引入函数式中间件 import { logger } from './middleware/logger.middleware'; app.use(logger);
管道
- 关于管道:https://docs.nestjs.com/pipes
- 管道的概念是主要用于将输入数据转换为所需的输出数据
- 或者处理Get,Post提交的数据
创建管道
$
nest g pipe cart
或指定路径生成 $
nest g middleware common/pipe/cart.pipe
创建一个cart的管道
import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; @Injectable() export class CartPipe implements PipeTransform { transform(value: any, metadata: ArgumentMetadata) { return value; } }
说明:管道是由@Injectable()装饰器装饰的一个类
需要实现 PipeTransform 这个接口,并且实现其内部的一个 transform 方法
这里有两个参数:value,metadata
其中, value是传递到管道里的数据, metadata是一种类型
在这里面可以修改传入的值以及验证传入值的合法性
使用管道
在控制器中使用管道
import { Controller, Get, Query, UsePipes} from '@nestjs/common'; //引入管道 import { CartPipe } from '../../pipe/cart.pipe'; @Controller('cart') export class NewsController { @Get() @UsePipes(new CartPipe()) index(@Query() info){ console.log(info); return 'Cart' } }
由上面的代码可知,先要引入管道,之后使用UsePipes将引入的管道实例作为参数作为当前路由的一项装饰器
这里的info就会被传入到管道里面,也就是管道里的value参数
之后,在管道里就可以针对当前的值进行修改,校验等操作
关于管道中的校验
在接收到数据前,需要对数据进行一些校验等操作,这时候就比较适合在管道中写相关程序
一般而言,我们会借助第三方的库来帮助我们完成校验,官方给我们提供了使用joi库相关的示例
https://github.com/hapijs/joi,https://joi.dev/api/?v=17.6.0
下面做一下演示
// 控制器文件中使用 import { Controller, Get, Query, UsePipes } from '@nestjs/common'; import { UserPipe } from '../../pipe/user.pipe'; import * as Joi from 'joi'; // 定义 json schema const userSchema = Joi.object().keys({ name: Joi.string().required(), age: Joi.number().integer().min(6).max(66).required(), }) @Controller('user') export class UserController { @Get() @UsePipes(new UserPipe(userSchema)) index(@Query() info) { console.log(info); return '用户中心'; } }
// 在管道文件中 import { ArgumentMetadata, Injectable, PipeTransform } from '@nestjs/common'; @Injectable() export class UserPipe implements PipeTransform { private schema; constructor(schema){ this.schema=schema // 实例化的时候,参数传入 } transform(value: any, metadata: ArgumentMetadata) { const { error } = this.schema.validate(value); // 进行校验 // 如果错误,则提示,或统一返回相同的实体数据结构, 比如给前端提示 if(error) { return { "success": false}; } return value; } }
上面是基础用法,当然一般而言,也可以添加相关message信息,用于给前端用户提示
更多用法,请参考上面文档
边栏推荐
- Embedded development program framework
- The video in win10 computer system does not display thumbnails
- L'introduction en bourse de MSK Electronics a pris fin: 800 millions de RMB d'actifs de Henan étaient des actionnaires
- MIT CMS. 300 session 8 – immersion / immersion
- 我想问一下 按照现在mysql-cdc的设计,全量阶段,如果某一个chunk的binlog回填阶段,
- Recommendation | recommendation of 9 psychotherapy books
- word封面下划线
- SQL注入漏洞(MSSQL注入)
- Postman关联
- canal同步mysql数据变化到kafka(centos部署)
猜你喜欢
MPLS experiment
Distributed transaction solution
麥斯克電子IPO被終止:曾擬募資8億 河南資產是股東
Easyrecovery靠谱不收费的数据恢复电脑软件
Orm-f & Q object
IPv6 comprehensive experiment
满足多元需求:捷码打造3大一站式开发套餐,助力高效开发
Postman前置脚本-全局变量和环境变量
L'introduction en bourse de MSK Electronics a pris fin: 800 millions de RMB d'actifs de Henan étaient des actionnaires
Redis - redis in action - redis actual combat - actual combat Chapter 1 - SMS login function based on redis - redis + token shared session application - with code
随机推荐
The most detailed and comprehensive update content and all functions of guitar pro 8.0
Canal synchronizes MySQL data changes to Kafka (CentOS deployment)
Dry goods collection | Vulkan game engine video tutorial
Word cover underline
How to realize automatic playback of H5 video
DMA use of stm32
View workflow
Scala function advanced
coreldraw2022新版本新功能介绍cdr2022
Leetcode 186 Flip the word II in the string (2022.07.05)
Fuzzy -- basic application method of AFL
Excellent PM must experience these three levels of transformation!
How to estimate the population with samples? (mean, variance, standard deviation)
关于imx8mp的es8316的芯片调试
ue5 小知识点 开启lumen的设置
A blog to achieve embedded entry
也算是學習中的小總結
团队协作出了问题,项目经理怎么办?
[HBZ share] reasons for slow addition and deletion of ArrayList and fast query
Platformio create libopencm3 + FreeRTOS project