typescript - NestJS Swagger 使用 Zod 的多部分文件上传问题
我正在开发一个 NestJS 应用程序,并使用 nestjs-zod 库进行验证和 swagger 文档。然而,当我尝试在 multipart form-data 请求中上传文件时,遇到了问题。
问题是我用来验证的 zod 没有特定的 File 类型,并且 Swagger 不会将其识别为文件输入,因为它缺少 @ApiProperty({ format: 'binary' }) 装饰。我正在寻找一种解决方案,以便使用 zod 正确地记录和验证多部分文件上传,同时我希望继续使用我正在做的 Dtos。
dto.tsimport { createZodDto } from 'nestjs-zod/dto';
import * as z from 'nestjs-zod/z';
export const schema = z.object({
field: z.string().optional(),
requiredFile: z
.string()
.refine((str: any): str is Buffer => Buffer.isBuffer(Buffer.from(str))),
optionalFile: z
.string()
.refine((str: any): str is Buffer => Buffer.isBuffer(Buffer.from(str)))
.optional(),
});
export class Dto extends createZodDto(schema) {}
controller.ts@Post()
@UseInterceptors(
FileFieldsInterceptor(
[{ name: 'requiredFile' }, { name: 'optionalFile' }],
multerLimits,
),
)
@ApiConsumes('multipart/form-data')
async create(
@Body() dto: CreateStoreDto,
@UploadedFiles()
files,
) {
// Handle the request...
}
我也尝试过使用 zod-to-openapi 包,但什么都没有改变!
dto2.tsimport { createZodDto } from 'nestjs-zod/dto';
import { z as z2 } from 'nestjs-zod/z';
import { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
extendZodWithOpenApi(z2);
export const schema = z2.object({
optionalFile: z2
.custom<Express.Multer.File>()
.openapi({ format: 'binary', type: 'string' }),
requiredFile: z2
.string()
.refine((str: any): str is Buffer => Buffer.isBuffer(Buffer.from(str)))
.openapi({ type: 'string', format: 'binary' }),
});
export class Dto extends createZodDto(schema) {}
我也尝试了
file3: z2.string().openapi({ type: 'string', format: 'binary' }),
但是那也不起作用
这是你可以 fork 并尝试提交 PR 修复问题的 GitHub 仓库: https://github.com/mohrazzak/nodejs
答案#1
我刚偶然发现这个,你的帖子帮我找到了答案。
image: z.custom<Express.Multer.File>().openapi({
type: 'string',
description: 'The image to classify',
format: 'binary'
})
这似乎在 ValidationPipe 下工作得很好,但仍然保持 openapi 规范正确。
答案#2
我用这个来解决这个问题
import { createZodDto } from '@anatine/zod-nestjs';
import { extendZodWithOpenApi, extendApi } from '@anatine/zod-openapi';
import { ProductSchema } from 'src/generated';
import { SupportedLanguages } from 'src/shared/enums/supported-languages.enum';
import * as z from 'zod';
extendZodWithOpenApi(z);
const baseSchema = ProductSchema.pick({
name: z.string(),
description: z.string()
);
const CreateProductDtoSchema = extendApi(baseSchema, {
properties: {
productImages: {
type: 'array',
minItems: 1,
items: { type: 'string', format: 'binary' },
},
},
required: ['productImages'],
});
export class CreateProductDto extends createZodDto(CreateProductDtoSchema) {}
