Nestjs FileInterceptor和DTO

发布于 2025-02-12 06:57:01 字数 4187 浏览 0 评论 0原文

我想用Swagger创建上传,使用DTO并将二进制保存在我的dto中

import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { IsNotEmpty, IsOptional } from 'class-validator';


export class GatewayDto {  
    
  @ApiProperty({ default: 'foo' })
  @IsNotEmpty()
  @Expose()
  name: string;
  
  @ApiProperty({default: 'XXXX:YYYY'})
  @IsNotEmpty()
  @Expose()
  token: string;

  @ApiProperty({default: '123'})
  @IsNotEmpty()
  @Expose()
  channelId: string;
  
  @ApiProperty({ default: true })  
  @IsNotEmpty()
  @Expose()
  public: string;

  @Expose()  
  @IsNotEmpty()
  logo: any;

}

我的控制器是:


 @Post('/')
    @ApiConsumes('multipart/form-data')
    @ApiBody({
        schema: {
            type: 'object',
            properties: {
                name: {
                    type: 'string',
                    default: 'foo'
                },
                token: {
                    type: 'string',
                    default: '11:22'
                },
                channelId: {
                    type: 'string',
                    default: '1234'
                },
                public: {
                    type: 'string',
                    default: 'true'
                },
                logo: {
                    type: 'string',
                    format: 'binary',                                        
                },
            },
        },
    })
    @UseInterceptors(FileInterceptor('logo'))
    @HttpCode(HttpStatus.CREATED)
    @ApiCreatedResponse(GatewayConfigSwagger.API_CREATE_GATEWAY)
    //@Serialize(GatewayDto)
    public async create(
        @UploadedFile('file') file,
        @Body() data: GatewayDto,
        @Request() request
    ) {
        console.log(data);
        
        if (file) {
            data['logo'] = file.buffer;
        }
        //return this.gatewayService.create(request.user.userId._id, data);
    }

当我创建我的请求时,我会收到此错误:

“徽标不应该为空”>

我的卷发是:

curl -X 'POST' \
  'http://localhost:3001/api/v1/gateways' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer xxx \
  -H 'Content-Type: multipart/form-data' \
  -F 'name=foo' \
  -F 'token=11:22' \
  -F 'channelId=1234' \
  -F 'public=true' \
  -F '[email protected];type=image/png'

如果我从DTO删除徽标字段,则可以存储图像。

我试图根据此答案创建一个拦截器 Swagger Nestjs中的其他数据


import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";

export interface Response<T> {
    statusCode: number;
    data: T;    
}

@Injectable()
export class FileExtender implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const req = context.switchToHttp().getRequest();
      console.log(req.body)
      
      return next.handle();
    }
  }

和我的req.body没有徽标字段

更新

我更新了我的Interceptor

import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";

export interface Response<T> {
    statusCode: number;
    data: T;    
}

@Injectable()
export class FileExtender implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const req = context.switchToHttp().getRequest();
      
      req.body['logo'] = req.file.buffer;   
      console.log(req.body)
      
      return next.handle();
    }
  }

现在它有效,但这是最好的做法吗?

I want to create upload with swagger,use DTO and save the binary in my MongoDB

My DTO is:

import { ApiProperty } from '@nestjs/swagger';
import { Expose } from 'class-transformer';
import { IsNotEmpty, IsOptional } from 'class-validator';


export class GatewayDto {  
    
  @ApiProperty({ default: 'foo' })
  @IsNotEmpty()
  @Expose()
  name: string;
  
  @ApiProperty({default: 'XXXX:YYYY'})
  @IsNotEmpty()
  @Expose()
  token: string;

  @ApiProperty({default: '123'})
  @IsNotEmpty()
  @Expose()
  channelId: string;
  
  @ApiProperty({ default: true })  
  @IsNotEmpty()
  @Expose()
  public: string;

  @Expose()  
  @IsNotEmpty()
  logo: any;

}

my controller is:


 @Post('/')
    @ApiConsumes('multipart/form-data')
    @ApiBody({
        schema: {
            type: 'object',
            properties: {
                name: {
                    type: 'string',
                    default: 'foo'
                },
                token: {
                    type: 'string',
                    default: '11:22'
                },
                channelId: {
                    type: 'string',
                    default: '1234'
                },
                public: {
                    type: 'string',
                    default: 'true'
                },
                logo: {
                    type: 'string',
                    format: 'binary',                                        
                },
            },
        },
    })
    @UseInterceptors(FileInterceptor('logo'))
    @HttpCode(HttpStatus.CREATED)
    @ApiCreatedResponse(GatewayConfigSwagger.API_CREATE_GATEWAY)
    //@Serialize(GatewayDto)
    public async create(
        @UploadedFile('file') file,
        @Body() data: GatewayDto,
        @Request() request
    ) {
        console.log(data);
        
        if (file) {
            data['logo'] = file.buffer;
        }
        //return this.gatewayService.create(request.user.userId._id, data);
    }

When I create my request, I get this error:

"logo should not be empty"

My curl is:

curl -X 'POST' \
  'http://localhost:3001/api/v1/gateways' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer xxx \
  -H 'Content-Type: multipart/form-data' \
  -F 'name=foo' \
  -F 'token=11:22' \
  -F 'channelId=1234' \
  -F 'public=true' \
  -F '[email protected];type=image/png'

If I remove the logo field from DTO I'm able to store my image.

I tried to create a interceptor according to this answer File uploading along with other data in Swagger NestJs


import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";

export interface Response<T> {
    statusCode: number;
    data: T;    
}

@Injectable()
export class FileExtender implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const req = context.switchToHttp().getRequest();
      console.log(req.body)
      
      return next.handle();
    }
  }

and my req.body doesn't have logo field

UPDATE

I updated my interceptor with

import { BadGatewayException, CallHandler, ExecutionContext, Injectable, NestInterceptor, UnauthorizedException } from "@nestjs/common";
import { catchError, map, Observable, throwError } from "rxjs";

export interface Response<T> {
    statusCode: number;
    data: T;    
}

@Injectable()
export class FileExtender implements NestInterceptor {
    intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
      const req = context.switchToHttp().getRequest();
      
      req.body['logo'] = req.file.buffer;   
      console.log(req.body)
      
      return next.handle();
    }
  }

Now it works, but is it the best practice?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不甘平庸 2025-02-19 06:57:01

尝试在DTO文件中使用@isoptional徽标属性上使用验证器。它用于标记无效字段。验证将通过它是nullundefined,并且将按照其他验证器执行。应用逻辑必须相应处理。

您可以查看所有可用的验证器在这里。您可以在任何DTO类属性上组合其中的任何数量。

Try using the @IsOptional validator on the logo property in the DTO file. It is used to mark nullable fields. Validation will pass if it is null or undefined and will be enforced as per other validators otherwise. Application logic must handle this accordingly.

You can take a look at all available validators here. You can combine any number of them on any DTO class property.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文