【NestJS】HTTP 接口传参的 5 种方式(含前端调用与后端接收)
【NestJS】HTTP 接口传参的 5 种方式
在前后端开发中,HTTP 接口的数据传输方式有多种,常见的有 query、url param、form-urlencoded、form-data、json。
作为前端,我们不仅要知道如何调用,还要理解后端如何接收。今天我们用 NestJS 来演示这几种方式。
目录
- 1. Query 参数
- 2. URL Param 参数
- 3. Form-Urlencoded
- 4. Form-Data
- 5. JSON
- 总结
1. Query 参数
参数位置
- 写在 URL ? 后面,多个参数用
&
分隔 - 例如:
GET /person?name=三十&age=18
前端调用
// axios 方式
axios.get('/api/person', {params: { name: '三十', age: 18 }
});// 或者直接拼接
axios.get('/api/person?name=三十&age=18');
后端定义
@Controller('api/person')
export class PersonController {@Get('/query')queryHandle(@Query('name') name: string, @Query('age') age: number) {return `[三十] queryHandle received name=${name}, age=${age}`;}
}
2. URL Param 参数
参数位置
- 直接放在 URL 路径中
- 例如:
GET /person/18
前端调用
axios.get('/api/person/18');
后端定义
@Controller('api/person')
export class PersonController {@Get(':id') // 声明参数,定义多个参数: @Get(':id/:age/:name')urlParamHandle(@Param('id') id: string) { // @Param() 装饰器,取出参数注入到 Controller 方法中return `[三十] urlParamHandle received id=${id}`;}
}
注意点: 静态路由和动态路由定义顺序
静态路由(find、list、detail 等)要放在前面, 动态路由(:id、:slug 等)要放在后面 ,否则静态路由会被动态路由“吃掉”
@Controller('api/person')
export class PersonController {@Get('find') // 静态路由findAll() {return 'find all';}@Get(':id') // 动态路由getById(@Param('id') id: string) {return { id };}
}
3. Form-Urlencoded
参数位置
- 写在 body 里,格式类似
name=三十&age=18
非英文字符和其他需要编码的字符可以通过
encodeURIComponent('三十')
编码或使用 query-string npm 包处理
-
Content-Type: application/x-www-form-urlencoded
前端调用
import qs from 'qs';const res = await axios.post('/api/person', qs.stringify({name: '三十',age: 18}), {headers: { 'content-type': 'application/x-www-form-urlencoded' }});
后端定义(NestJS)
// dto 是 data transfer object,用于封装传输的数据的对象
class CreatePersonDto {name: string;age: number;
}@Controller('api/person')
export class PersonController {@Post()formUrlEncodedHandle(@Body() createPersonDto: CreatePersonDto) { // 使用 @Body 装饰器,Nest 会解析请求体,然后注入到 dto 中。return `[三十] formUrlEncodedHandle received ${JSON.stringify(createPersonDto)}`}
}
4. Form-Data
参数位置
-
也是写在 body 中
-
使用
boundary
分隔,支持上传 文件 -
Content-Type: multipart/form-data
前端调用
import axios from 'axios'
const fileInput = document.querySelector('#fileInput');async function formData() {const data = new FormData();data.set('name','三十');data.set('age', 18);data.set('file1', fileInput.files[0]);data.set('file2', fileInput.files[1]);axios.post('/api/person/file', data, {headers: { 'content-type': 'multipart/form-data' }});
}fileInput.onchange = formData;
后端定义
import {Body,UseInterceptors,UploadedFiles,
} from '@nestjs/common';
import { PersonService } from './person.service';
import { AnyFilesInterceptor } from '@nestjs/platform-express';@Controller('api/person')
export class PersonController {@Post('file')@UseInterceptors(AnyFilesInterceptor({dest: 'upload/', // 默认上传文件存放的目录}),)formDataHandle(@Body() createPersonDto: CreatePersonDto,@UploadedFiles() files: Array<Express.Multer.File>,) {console.log(files);return `[三十] formDataHandle received ${JSON.stringify(createPersonDto)}`;}
}
5. JSON
参数位置
- 写在 body 中
Content-Type: application/json
前端调用
axios.post('/api/person', {name: '三十',age: 18
});
后端定义(NestJS)
@Controller('api/person')
export class PersonController {@Post()applicationJsonHandle(@Body() createPersonDto: CreatePersonDto) {return `[三十] applicationJsonHandle received ${JSON.stringify(createPersonDto)}`;}
}
总结
方式 | 参数位置 | Content-Type | 前端调用示例 | NestJS 装饰器 |
---|---|---|---|---|
Query | URL ? 后面 | 无需特殊设置 | axios.get('/api?x=1') | @Query |
URL Param | URL 路径 | 无需特殊设置 | axios.get('/api/1') | @Param |
Form-Urlencoded | body(字符串) | application/x-www-form-urlencoded | axios.post(url, qs.stringify()) | @Body |
Form-Data | body(分隔符) | multipart/form-data | axios.post(url, formData) | @Body + @UploadedFile |
JSON | body(JSON) | application/json | axios.post(url, { obj }) | @Body |