Cookie
-
Cookie
的处理与平台有关系,以Express
平台为例,安装Express
的插件;npm i cookie-parser --save
-
main.ts
//因为TypeScript的关系,需要使用 import 的方式引入,而不是node中常用的require() import * as cookieParser from 'cookie-parser' // 引入中间件 app.use(cookieParser());
- 设置
Cookie
@Get('set') find(@Response() res) { res.cookie('name', 'Machal', { maxAge: 900000, httpOnly:true }); res.send('响应的信息'); // 直接操作Response }
- 使用了响应对象
Response
时,如果没有返回渲染模板时,控制器方法中不能通过return
返回数据,否则无法结束本次响应; - 如果返回了模板视图,则可以使用
return
返回数据,只不过这些数据是供模板视图使用的。
- 使用了响应对象
- 获取
Cookie
@Get('cook') find(@Request() req) { return req.cookies.name }
- 加密
Cookie
// 用作加密的字符串 app.use(cookieParser('signed cookie')); // 启用加密 res.cookie('name', 'Machal', { maxAge: 900000, httpOnly:true, signed: true }); // 获取加密Cookie req.signedCookies.name
Session
-
Session
也与当前nestjs
中所使用平台有关,以Express
平台为例;npm i express-session --save
-
main.ts
import * as session from 'express-session' // 引入中间件 app.use(session({ secret: 'keyboard cat', cookie: {maxAge:6000, httpOnly:true}, rolling:true }));
- 设置:
@Get('sets') setSession(@Request() req) { req.session.age= 20; // 设置Session return 'sucess'; }
- 获取
- 方式一:
let age = req.session.age
- 方式二:
@Session()
@Get('sess') getSession(@Session() sess) { console.log(sess.age); // 20 return 'sucess'; }
- 方式一:
- 销毁
// 手动销毁 req.session.destroy(callback); // 把过期时间设置为0,自动销毁 req.session.cookie.maxAge = 0;
文件上传
- 表单
Form
属性必须设置为enctype="multipart/form-data"
- 文档:
https://docs.nestjs.com/techniques/file-upload
单个文件上传
- 表单
<from action="/upload/add" method="post" enctype="multipart/form-data"> <input type="text" name="title" /> <input type="text" name="keyword" /> <input type="file" name="pic" /> <input type="submit" value="提交" /> </from>
- 引入
nestjs
的装饰器、Express
平台的拦截器import { UseInterceptors, UploadedFile } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express';
-
FileInterceptor()
可接收两个参数:name(键)、options(可选参数对象)
- 控制器:通过Node的
fs
模块写入文件import { createWriteStream } from 'fs' import { join } from 'path' @Controller('upload') export class UploadController { @Post('add') @UseInterceptors(FileInterceptor('pic')) // <input type="file" name="pic" /> doAdd(@Body() body, @UploadedFile() file) { // 普通键值对封装在 body 中 // 文件则封装在file中的 buffer 属性 var ws = createWriteStream(join(__dirname, '../../public/upload', file.originalname)); ws.write(file.buffer); return '上传成功!'; } }
-
file
{ fieldname: '键名', originalname: '文件名', encoding: 'xxx', mimetype: '文件MIME类型', // 可用于判断上传的文件是否符合要求 buffer: 'buffer对象', size: 文件大小 }
上传多个文件
- 引入
nestjs
的装饰器、Express
平台的拦截器import { UseInterceptors, UploadedFiles } from '@nestjs/common';
- 多个文件的键可能相同,也可能不同;
- 键相同时,使用
Express
平台的FilesInterceptor
<input type="file" name="pic" /> <input type="file" name="pic" />
import { FilesInterceptor } from '@nestjs/platform-express';
-
FilesInterceptor()
的三个参数:name(键)、maxCount(同时上传的最大文件数)、MulterOptions(可选参数对象)
@Post('add') @UseInterceptors(FilesInterceptor('pic')) doAdd(@Body() body, @UploadedFiles() files) { // files 是一个数组 }
-
- 键不同时,使用
Express
平台的FileFieldsInterceptor
<input type="file" name="avatar" /> <input type="file" name="background" />
@Post('add') @UseInterceptors(FileFieldsInterceptor([ { name: 'avatar', maxCount: 1 }, { name: 'background', maxCount: 1 }, ])) uploadFile(@UploadedFiles() files) { console.log(files); }
- 不想关心键名时,使用
Express
平台的AnyFilesInterceptor
@Post('add') @UseInterceptors(AnyFilesInterceptor()) uploadFile(@UploadedFiles() files) { console.log(files); }
中间件
- 中间件就是在匹配路由之前或之后做的一系列操作,并通过
next()
继续向下匹配; -
nestjs
中间件可以是一个函数,也可以是一个@Injectable()
装饰的类 - 创建中间件
nest g middleware middleware/init // 在 middleware 目录中创建init中间件
middleware/init.moddleware.ts
import { Injectable, NestMiddleware } from '@nestjs/common'; @Injectable() export class InitMiddleware implements NestMiddleware { use(req: any, res: any, next:()=>void) { console.log('---- init ----'); next(); } }
- 在根模块中配置中间件:
app.module.ts
import { Module, NestModule, MiddlewareConsumer, RequestMethod } from '@nestjs/common'; import { InitMiddleware } from './middleware/init.moddleware'; @Module({...}) export class AppModule implements NestModule { configure(consumer: MiddlewareConsumer) { consumer .apply(InitMiddleware) // 配置执行的中间件 .forRoutes('*') // 配置匹配的路由,* 表示匹配所有的路由 } }
-
forRoutes()
配置匹配路由的方式有很多;-
forRoutes('user')
:只匹配user
路由; -
forRoutes('ab*cd')
:模糊匹配; -
forRoutes(UserController)
:传入一个控制器,只匹配这个控制器的路由; -
forRoutes({ path:'user', method:RequestMethod.GET })
:指定路由的同时,再限定其请求方法; -
forRoutes({ path:'user', method:RequestMethod.GET }, { path:'user', method:RequestMethod.ALL })
:配置多个路由;
-
- 不同路由匹配不同的中间件
import { Injectable, NestMiddleware } from '@nestjs/common'; import { Request, Response } from 'express'; @Injectable() export class UserMiddleware implements NestMiddleware { use(req: Request, res: Response, next: Function) { console.log('---- user ----'); next(); } }
consumer .apply(InitMiddleware).forRoutes('*') .apply(UserMiddleware).forRoutes('user')
- 所有路由都匹配
InitMiddleware
中间件; -
user
路由同时匹配InitMiddleware
和UserMiddleware
- 所有路由都匹配
-
apply()
支持同时配置多个中间件consumer .apply(InitMiddleware, UserMiddleware) .forRoutes('user') // user路由同时匹配InitMiddleware和UserMiddleware
-
exclude()
可以排除某些路由;但不适用于函数中间件,也不排除通用路由(例如,通配符)的路径。consumer .apply(UserMiddleware) .exclude( { path: 'cats', method: RequestMethod.GET }, { path: 'cats', method: RequestMethod.POST }) .forRoutes('user')
- 函数式中间件
function logger(req, res, next) { console.log('---- logger ----'); next(); } consumer .apply(UserMiddleware, logger).forRoutes('user')
- 全局中间件
- 在
main.ts
中,通过app.use()
应用的中间件; -
app.use()
不能引用类中间件,只能是函数式中间件。
- 在
网友评论