请求参数处理
本教程共 47 篇 · 第 12 篇 · 更新于 2026-08-09 · 约 10 分钟阅读
本节目标:掌握从 HTTP 请求中提取各种参数的方式,学会用 DTO 做数据验证,以及自定义参数装饰器。
参数提取装饰器一览
NestJS 提供了一组装饰器,帮你从请求的不同位置提取数据:
| 装饰器 | 提取来源 | 示例 |
|---|---|---|
@Param() | URL 路径参数 | /users/:id |
@Query() | 查询字符串 | ?page=1&limit=10 |
@Body() | 请求体 | POST/PUT 的 JSON 数据 |
@Headers() | 请求头 | Authorization: Bearer xxx |
@Cookies() | Cookie | token=abc123 |
@Session() | Session | 会话数据 |
@Ip() | 客户端 IP | 请求来源 IP |
@Param() — 路径参数
从 URL 路径中提取动态值:
@Get(':id')
findOne(@Param('id') id: string) {
return `用户 ID: ${id}`;
}
访问 GET /users/42,id 的值是 '42'。
多个路径参数:
@Get(':userId/posts/:postId')
getUserPost(
@Param('userId') userId: string,
@Param('postId') postId: string,
) {
return `用户 ${userId} 的文章 ${postId}`;
}
一次拿全部:
@Get(':userId/posts/:postId')
getUserPost(@Param() params: { userId: string; postId: string }) {
return params;
}
类型转换
URL 参数默认是字符串。如果需要数字类型,用 ParseIntPipe:
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number) {
return typeof id; // 'number'
}
如果传的不是数字(比如 /users/abc),ParseIntPipe 会直接抛 400 错误。
@Query() — 查询参数
从 URL 查询字符串中提取数据:
@Get()
findAll(
@Query('page') page: string,
@Query('limit') limit: string,
) {
return `第 ${page} 页,每页 ${limit} 条`;
}
访问 GET /users?page=1&limit=10。
一次拿全部查询参数:
@Get()
findAll(@Query() query: Record<string, string>) {
return query;
}
用 DTO 组织查询参数
查询参数多了之后,用 DTO 来组织更清晰:
import { IsOptional, IsInt, Min } from 'class-validator';
import { Type } from 'class-transformer';
export class PaginationDto {
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
page?: number = 1;
@IsOptional()
@Type(() => Number)
@IsInt()
@Min(1)
limit?: number = 10;
}
@Get()
findAll(@Query() pagination: PaginationDto) {
return pagination;
}
Tip
@Type(() => Number)配合ValidationPipe的transform: true选项,能把字符串自动转成数字。不然?page=1拿到的还是字符串'1'。
@Body() — 请求体
从 POST/PUT 请求的 body 中提取数据:
@Post()
create(@Body() createUserDto: CreateUserDto) {
return this.usersService.create(createUserDto);
}
提取单个字段:
@Post()
create(
@Body('name') name: string,
@Body('email') email: string,
) {
return { name, email };
}
DTO 验证
用 class-validator 给 DTO 加验证规则:
npm install class-validator class-transformer
import { IsString, IsEmail, IsInt, Min, Max, IsOptional, IsNotEmpty } from 'class-validator';
export class CreateUserDto {
@IsString()
@IsNotEmpty()
name: string;
@IsEmail()
email: string;
@IsInt()
@Min(0)
@Max(150)
age: number;
@IsOptional()
@IsString()
bio?: string;
}
在 main.ts 里开启全局验证管道:
import { ValidationPipe } from '@nestjs/common';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(new ValidationPipe({
whitelist: true, // 自动过滤 DTO 中未定义的属性
forbidNonWhitelisted: true, // 有未定义属性时直接报错
transform: true, // 自动类型转换
}));
await app.listen(3000);
}
bootstrap();
Note
whitelist: true非常实用。如果客户端传了 DTO 里没有的字段,会被自动过滤掉。防止恶意用户注入意外数据。
@Headers() — 请求头
@Get()
findAll(@Headers('authorization') auth: string) {
return `Token: ${auth}`;
}
获取所有请求头:
@Get()
findAll(@Headers() headers: Record<string, string>) {
return headers;
}
@Cookies() — Cookie
需要先安装 cookie-parser:
npm install cookie-parser
在 main.ts 中配置:
import * as cookieParser from 'cookie-parser';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.use(cookieParser());
await app.listen(3000);
}
bootstrap();
然后就能用了:
@Get()
findAll(@Cookies('token') token: string) {
return { token };
}
文件上传
单文件上传
import {
Controller, Post, UseInterceptors, UploadedFile,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
@Controller('upload')
export class UploadController {
@Post()
@UseInterceptors(FileInterceptor('file'))
uploadFile(@UploadedFile() file: Express.Multer.File) {
return {
filename: file.originalname,
size: file.size,
mimetype: file.mimetype,
};
}
}
FileInterceptor('file') 里的 'file' 是表单字段名。前端上传时,文件字段的 name 必须是 file。
多文件上传
@Post('multiple')
@UseInterceptors(FilesInterceptor('files', 10))
uploadFiles(@UploadedFiles() files: Express.Multer.File[]) {
return files.map(f => ({ name: f.originalname, size: f.size }));
}
多字段文件上传
@Post('fields')
@UseInterceptors(
FileFieldsInterceptor([
{ name: 'avatar', maxCount: 1 },
{ name: 'documents', maxCount: 10 },
]),
)
uploadFiles(
@UploadedFiles() files: {
avatar?: Express.Multer.File[];
documents?: Express.Multer.File[];
},
) {
return files;
}
Tip文件上传默认存在内存里。生产环境建议配合
multer的磁盘存储,或者上传到 OSS/S3。
自定义参数装饰器
如果你经常需要获取当前登录用户的信息,可以封装一个自定义装饰器:
import { createParamDecorator, ExecutionContext } from '@nestjs/common';
export const CurrentUser = createParamDecorator(
(data: string, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
return data ? user?.[data] : user;
},
);
使用方式:
@Get('profile')
getProfile(@CurrentUser() user: User) {
return user;
}
@Get('email')
getEmail(@CurrentUser('email') email: string) {
return { email };
}
@CurrentUser() 获取整个用户对象,@CurrentUser('email') 获取用户的 email 字段。
Note自定义装饰器依赖
request.user,这通常是认证守卫(Guard)设置的。后面学守卫时会详细讲。
小结
请求参数处理是 NestJS 开发中最常用的操作。
核心装饰器:
@Param()— 路径参数@Query()— 查询参数@Body()— 请求体@Headers()— 请求头@Cookies()— Cookie
进阶技巧:
- 用 DTO +
class-validator做数据验证 - 用
ValidationPipe的whitelist和transform选项 - 用
createParamDecorator封装自定义装饰器