神光《Nest 通关秘籍》学习总结-五种数据HTTP数据传输方式

1,675 阅读3分钟

最近在学习神光大神的《Nest通关秘籍》,该小册主要包含下面这些内容:

image.png 现在购买还有优惠,《传送门

接下来的日子里,我将更新一系列的学习笔记。感兴趣的可以关注我的专栏《Nest 通关秘籍》学习总结

特别申明:本系列文章已经经过作者本人的允许。 大家也不要想着白嫖,我的笔记只是个人边学习边记录的,不是很完整,大家想要深入学习还是要自己去购买原版小册。

本节课我们来学习五种数据HTTP数据传输方式:

  • url param
  • query
  • form-urlencoded
  • form-data
  • json

准备:测试项目

前置条件:使用 nest new project-name生成一个nest项目。

使用nest g gernrate person创建一个person模块.

访问:http://localhost:3000/person/1, 我这里使用的apifox进行测试的:

如果你的也跟图中一样的,这就证明我们的api 接口跑通了。

再支持下静态资源的访问:调用下 useStaticAssets 来支持静态资源的请求:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express';
import { join } from 'path';

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

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

访问http://localhost:3000/static/index.html,即可看到页面。

然后我们在index.html添加一个接口氢气。修改文件中的内容,试着访问一个param形式的接口

<!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>

打开页面中的控制台,发现接口已经返回数据请求了

OK,现在一切准备就绪,接下来我们通过nest接口和前端进行联调的方式来认识五种数据HTTP数据传输方式。

1.url param

现在我们如下一个请求地址:

http://xiumubai.com/person/1111

这里的 1111 就是路径中的参数(url param),服务端框架或者单页应用的路由都支持从 url 中取出参数。

示例代码:

@Get(':id')
  findOne(@Param('id') id: string) {
    return this.personService.findOne(+id);
  }

修改index.html中的请求如下:

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

这里的1就是我们拿到的id。这个就是一个最基本的通过param传递数据的方式。

2.query

http://xiumubai.com/person?name=xiumubai&age=20

这里的 nameage 就是 query 传递的数据

示例代码:

@Get('find')
  query(@Query('name') name: string, @Query('age') age: number) {
    return `recived name:${name}, age: ${age}`;
  }
 const res = await axios.get('/api/person/find', {
    params: {
      name: '白哥',
      age: 18
    }
  });

这里我们传参的方式就变成了

{
    params: {
      name: '白哥',
      age: 18
    }
}

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);
  }
<!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 src="https://unpkg.com/qs@6.10.2/dist/qs.js"></script>
</head>
<body>
  <script>
    async function urlParam() {
      const res = await axios.post('/api/person', Qs.stringify({
            name: '白哥',
            age: 20
        }), {
            headers: { 'content-type': 'application/x-www-form-urlencoded' }
        });
        console.log(res);         
    }
    urlParam();
</script>
</body>
</html>

其实比起 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 来取。

示例代码:

@Post('file')
  @UseInterceptors(
    AnyFilesInterceptor({
      dest: 'uploads/',
    }),
  )
  filebody(
    @Body() createPersonDto: CreatePersonDto,
    @UploadedFiles() files: Array<Express.Multer.File>,
  ) {
    console.log(files);
    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>
</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>

可以看到,我们在nest中已经接收到了文件。

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)}`;
  }

前端代码使用 axios 发送 post 请求,默认传输 json 就会指定 content type 为 application/json,不需要手动指定:

<!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>

现在我们在日常开发传递POST参数基本上都是通过这种方式来开发。

以上就是我们在开发中遇到的5种常见的HTTP数据传输方式。