基础-2

Cookie

  1. Cookie的处理与平台有关系,以Express平台为例,安装Express的插件;
    npm i cookie-parser --save
    
  2. main.ts
    //因为TypeScript的关系,需要使用 import 的方式引入,而不是node中常用的require()
    import * as cookieParser from 'cookie-parser'
    // 引入中间件
    app.use(cookieParser());
    
  3. 设置Cookie
    @Get('set')
    find(@Response() res) {
        res.cookie('name', 'Machal', { maxAge: 900000, httpOnly:true });
        res.send('响应的信息');  // 直接操作Response
    }
    
    1. 使用了响应对象Response时,如果没有返回渲染模板时,控制器方法中不能通过 return 返回数据,否则无法结束本次响应;
    2. 如果返回了模板视图,则可以使用 return 返回数据,只不过这些数据是供模板视图使用的。
  4. 获取Cookie
    @Get('cook')
    find(@Request() req) {
        return req.cookies.name
    }
    
  5. 加密Cookie
    // 用作加密的字符串
    app.use(cookieParser('signed cookie'));
    // 启用加密
    res.cookie('name', 'Machal', { maxAge: 900000, httpOnly:true, signed: true });
    // 获取加密Cookie
    req.signedCookies.name
    

Session

  1. Session 也与当前nestjs中所使用平台有关,以Express平台为例;
    npm i express-session --save
    
  2. main.ts
    import * as session from 'express-session'
    // 引入中间件
    app.use(session({ secret: 'keyboard cat', cookie: {maxAge:6000, httpOnly:true}, rolling:true }));
    
  3. 设置:
    @Get('sets')
    setSession(@Request() req) {
        req.session.age= 20;  // 设置Session
        return 'sucess';
    }
    
  4. 获取
    1. 方式一:let age = req.session.age
    2. 方式二:@Session()
    @Get('sess')
    getSession(@Session() sess) {
        console.log(sess.age);   // 20
        return 'sucess';
    }
    
  5. 销毁
    // 手动销毁
    req.session.destroy(callback);
    
    // 把过期时间设置为0,自动销毁
    req.session.cookie.maxAge = 0;
    

文件上传

  1. 表单Form属性必须设置为 enctype="multipart/form-data"
  2. 文档:https://docs.nestjs.com/techniques/file-upload

单个文件上传

  1. 表单
    
        
        
        
        
    
    
  2. 引入nestjs的装饰器、Express平台的拦截器
    import { UseInterceptors, UploadedFile } from '@nestjs/common';
    import { FileInterceptor } from '@nestjs/platform-express';
    
  3. FileInterceptor()可接收两个参数:name(键)、options(可选参数对象)
  4. 控制器:通过Node的 fs 模块写入文件
    import { createWriteStream } from 'fs'
    import { join } from 'path'
    
    @Controller('upload')
    export class UploadController {
        @Post('add')
        @UseInterceptors(FileInterceptor('pic'))  // 
        doAdd(@Body() body, @UploadedFile() file) {
            // 普通键值对封装在 body 中
            // 文件则封装在file中的 buffer 属性
            var ws = createWriteStream(join(__dirname, '../../public/upload', file.originalname));
            ws.write(file.buffer);
            return '上传成功!';
        }
    }
    
  5. file
    {
        fieldname: '键名',
        originalname: '文件名',
        encoding: 'xxx',
        mimetype: '文件MIME类型',  // 可用于判断上传的文件是否符合要求
        buffer: 'buffer对象',
        size: 文件大小
    }
    

上传多个文件

  1. 引入nestjs的装饰器、Express平台的拦截器
    import { UseInterceptors, UploadedFiles } from '@nestjs/common';
    
  2. 多个文件的键可能相同,也可能不同;
  3. 键相同时,使用Express平台的FilesInterceptor
    
    
    
    import { FilesInterceptor } from '@nestjs/platform-express';
    
    1. FilesInterceptor()的三个参数:name(键)、maxCount(同时上传的最大文件数)、MulterOptions(可选参数对象)
    @Post('add')
    @UseInterceptors(FilesInterceptor('pic'))
    doAdd(@Body() body, @UploadedFiles() files) {
        // files 是一个数组
    }
    
  4. 键不同时,使用Express平台的FileFieldsInterceptor
    
    
    
    @Post('add')
    @UseInterceptors(FileFieldsInterceptor([
        { name: 'avatar', maxCount: 1 },
        { name: 'background', maxCount: 1 },
    ]))
    uploadFile(@UploadedFiles() files) {
        console.log(files);
    }
    
  5. 不想关心键名时,使用Express平台的AnyFilesInterceptor
    @Post('add')
    @UseInterceptors(AnyFilesInterceptor())
    uploadFile(@UploadedFiles() files) {
        console.log(files);
    }
    

中间件

  1. 中间件就是在匹配路由之前或之后做的一系列操作,并通过 next() 继续向下匹配;
  2. nestjs中间件可以是一个函数,也可以是一个 @Injectable() 装饰的类
  3. 创建中间件
    nest g middleware middleware/init  // 在 middleware 目录中创建init中间件
    
    1. 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();
        }
    }
    
    1. 在根模块中配置中间件: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('*')  // 配置匹配的路由,* 表示匹配所有的路由
        }
    }
    
  4. forRoutes() 配置匹配路由的方式有很多;
    1. forRoutes('user'):只匹配 user路由;
    2. forRoutes('ab*cd'):模糊匹配;
    3. forRoutes(UserController):传入一个控制器,只匹配这个控制器的路由;
    4. forRoutes({ path:'user', method:RequestMethod.GET }):指定路由的同时,再限定其请求方法;
    5. forRoutes({ path:'user', method:RequestMethod.GET }, { path:'user', method:RequestMethod.ALL }):配置多个路由;
  5. 不同路由匹配不同的中间件
    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')
    
    1. 所有路由都匹配 InitMiddleware 中间件;
    2. user路由同时匹配 InitMiddlewareUserMiddleware
  6. apply()支持同时配置多个中间件
    consumer
        .apply(InitMiddleware, UserMiddleware)
        .forRoutes('user')  // user路由同时匹配InitMiddleware和UserMiddleware
    
  7. exclude() 可以排除某些路由;但不适用于函数中间件,也不排除通用路由(例如,通配符)的路径。
    consumer
        .apply(UserMiddleware)
        .exclude(
            { path: 'cats', method: RequestMethod.GET },
            { path: 'cats', method: RequestMethod.POST })
        .forRoutes('user')
    
  8. 函数式中间件
    function logger(req, res, next) {
        console.log('---- logger ----');
        next();
    }
    
    consumer
        .apply(UserMiddleware, logger).forRoutes('user')
    
  9. 全局中间件
    1. main.ts 中,通过 app.use() 应用的中间件;
    2. app.use()不能引用类中间件,只能是函数式中间件。

你可能感兴趣的:(基础-2)