nestjs 简单接口

136 阅读2分钟

简单接口

nest g res person

image.png

import { Module } from '@nestjs/common';

import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PersonController } from './modules/person/person.controller';
import { PersonModule } from './modules/person/person.module';
import { PersonService } from './modules/person/person.service';

@Module({
    imports: [PersonModule],
    controllers: [AppController, PersonController],
    providers: [AppService, PersonService],
})
export class AppModule {}

localhost:3000/person/1

测试可以

支持下静态资源的访问

import { join } from 'path';

import { NestFactory } from '@nestjs/core';

import { NestExpressApplication } from '@nestjs/platform-express';

import { AppModule } from './app.module';

async function bootstrap() {
    const app = await NestFactory.create<NestExpressApplication>(AppModule);
    app.useStaticAssets(join(__dirname, '..', 'public'), { prefix: '/static' });
    await app.listen(3000);
}
bootstrap();

在根目录创建public,然后创建一个index.html文件。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
  <script>
    async function urlParam() {
        const res = await axios.get('/api/person/1');
        console.log(res);            
    }
    urlParam();
</script>
</body>
</html>

await axios.get('/api/person/1'); 请求前面有个api 先删掉 测试 localhost:3000/static/index.html

image.png

设置全局路由前缀'api'

在你的项目的main.ts文件中

import { join } from 'path';

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';

import { AppModule } from './app.module';

async function bootstrap() {
    const app = await NestFactory.create<NestExpressApplication>(AppModule);
    app.setGlobalPrefix('api');
    app.useStaticAssets(join(__dirname, '..', 'public'), { prefix: '/static' });
    await app.listen(3000);
}
bootstrap();

五种数据HTTP数据传输方式

1.param

person/1

await axios.get('/api/person/1');

上面就是模拟这种方式

2.query

localhost:3000/api/person/find?name=xiumubai&age=20

    // 路径find 方法get
    @Get('find')
    ceshi(@Query('name') name: string, @Query('age') age: number) {
        return `接收ceshi name:${name}, age: ${age}`;
    }
const res = await axios.get('/api/person/find', {
        params: {
          name: '白哥',
          age: 1811
        }
      });
const res = await axios.get('/api/person/find?name=ce&age=11');

两种方式都可以

tip: TSC编译好像有问题,会卡着,然后修改不生效,导致我查错查好久,但是又没报错误,很不爽,而且输出的信息太多,又不是重要的 所以我打算更换另一个SWC

pnpm add @swc/cli @swc/core -D
nest-cli.json
{
    "$schema": "https://json.schemastore.org/nest-cli",
    "collection": "@nestjs/schematics",
    "sourceRoot": "src",
    "compilerOptions": {
        "deleteOutDir": true,
        "builder": "swc",
        "typeCheck": true
    }
}

热更新速度很快

3.form-urlencoded

直接用 form 表单提交数据就是这种,它和 query 字符串的方式的区别只是放在了 body 里,然后指定下 content-type 是 application/x-www-form-urlencoded

@Post()
  create(@Body() createPersonDto: CreatePersonDto) {
    return `received: ${JSON.stringify(createPersonDto)}`;
    // return this.personService.create(createPersonDto);
  }
const res = await axios.post('/api/person', Qs.stringify({
        name: '白哥',
        age: 20
      }), {
        headers: { 'content-type': 'application/x-www-form-urlencoded' }
      });

tip: 发现新问题 原来的静态资源没法用了 可能跟swc有关 => 就是swc的问题,回撤

{
  "$schema": "https://json.schemastore.org/nest-cli",
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "deleteOutDir": true
  }
}

MD

qs没有引入

<script src="https://cdn.bootcss.com/qs/6.7.0/qs.min.js"></script>

其实比起 form urlencoded,使用 json 来传输更常用一些

4.form-data

form data 不再是通过 & 分隔数据,而是用 --------- + 一串数字做为 boundary 分隔符。因为不是 url 的方式了,自然也不用再做 url encode。

form-data 需要指定 content type 为 multipart/form-data,然后指定 boundary 也就是分割线。

body 里面就是用 boundary 分隔符分割的内容。

Nest 解析 form data 使用 FilesInterceptor 的拦截器,用 @UseInterceptors 装饰器启用,然后通过 @UploadedFiles 来取。非文件的内容,同样是通过 @Body 来取。

=》简单说就是文件传输用的是这个方式 如果非文件内容直接在nest中用@Body取内容

@Post('file')
  @UseInterceptors(
    AnyFilesInterceptor({
      dest: 'uploads/',
    }),
  )
  filebody(
    @Body() createPersonDto: CreatePersonDto,
    @UploadedFiles() files: Array<Express.Multer.File>,
  ) {
    console.log(files);
    return `received: ${JSON.stringify(createPersonDto)}`;
  }

报错: 命名空间“global.Express”没有已导出的成员“Multer”。

=》pnpm i @types/multer

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script>
</head>
<body>
  <input id="fileInput" type="file" multiple/>
  <script>
    const fileInput = document.querySelector('#fileInput');
    async function formData() {
        const data = new FormData();
        data.set('name','白哥');
        data.set('age', 20);
        data.set('file1', fileInput.files[0]);
        data.set('file2', fileInput.files[1]);

        const res = await axios.post('/api/person/file', data, {
            headers: { 'content-type': 'multipart/form-data' }
        });
        console.log(res);     
    }

    fileInput.onchange = formData;
</script>
</body>
</html>

image.png

在后端,文件会被怎么处理呢? 在项目中多了个uploads的文件夹和两个没有后缀的文件

image.png

5.json

form-urlencoded 需要对内容做 url encode,而 form data 则需要加很长的 boundary,两种方式都有一些缺点。如果只是传输 json 数据的话,不需要用这两种。

可以直接指定content type 为 application/json 就行。

我们平时传输 json 数据基本用的是这种。

@Post()
  create(@Body() createPersonDto: CreatePersonDto) {
    return `received: ${JSON.stringify(createPersonDto)}`;
  }
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://unpkg.com/axios@0.24.0/dist/axios.min.js"></script></script>
</head>
<body>
  <script>
    async function urlParam() {
      const res = await axios.post('/api/person', {
            name: '白哥',
            age: 20
        });
        console.log(res);         
    }
    urlParam();
</script>
</body>
</html>
对比下query的方式
 const res = await axios.get('/api/person/find', {
    params: {
      name: '白哥',
      age: 18
    }
  });