最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Nestjs: Image uploaded even if body validation fails - Stack Overflow

programmeradmin0浏览0评论

First of all, I apologize for my weak English.

I have a method that accepts PUT request, and it receives a file and BlogModel. When I submit the form from frontend and the BlogModel's validation is failed the file is still uploaded.

main.ts

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

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  app.useStaticAssets(join(__dirname, '..', 'src/public'));
  app.setBaseViewsDir(join(__dirname, '..', 'src/views'));

  app.setViewEngine('hbs');
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

addBlog method


  @Put()
  @UseInterceptors(FileInterceptor('thumbnail', { storage: BlogStorage }))
  addBlog(@UploadedFile() file, @Body() addBlogModel: AddBlogModel) {
    console.log(file);
  }

add-blog.model.ts

import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, Length } from 'class-validator';
import { Expose } from 'class-transformer';

export class AddBlogModel {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsString()
  @Length(10, 225)
  @IsOptional()
  introduction: string;

  @IsNotEmpty()
  @IsString()
  content: string;

  @IsBoolean()
  @Expose({name: 'is_published'})
  isPublished: boolean;

  @IsArray()
  @IsNotEmpty()
  tags: string[];

  @IsString()
  @IsNotEmpty()
  category: string;
}

index.hbs

<!DOCTYPE html>
<html>
<head>

</head>

<body>
<form id="form">
    <input name="title" id="title"/>
    <input name="content" id="content"/>
    <input type="file" name="thumbnail" id="thumbnail"/>

    <button type="submit">Submit</button>
</form>

<script src=".js"></script>
<script src=".19.0/axios.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $("#form").on('submit', function (e) {
            e.preventDefault();
            const data = $(this).serializeArray()
            const data_from_array = {}
            var formData = new FormData()

            $.map(data, function(n, i){
                formData.append(n['name'], n['value'])
            });

            const file = $('input[type="file"]')[0].files[0]

            formData.append('thumbnail', file)

            const config = {
                headers: {
                    'content-type': 'multipart/form-data'
                }
            }
            axios.put('http://localhost:3000/blogs', formData, config).then(res => {
                console.log(res)
            }).catch(err => {
                console.log(err.response)
            })
        });
    })
</script>
</body>
</html>

I expect the file is not uploaded if the validation is failed.

First of all, I apologize for my weak English.

I have a method that accepts PUT request, and it receives a file and BlogModel. When I submit the form from frontend and the BlogModel's validation is failed the file is still uploaded.

main.ts

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

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  app.useStaticAssets(join(__dirname, '..', 'src/public'));
  app.setBaseViewsDir(join(__dirname, '..', 'src/views'));

  app.setViewEngine('hbs');
  app.useGlobalPipes(new ValidationPipe());
  await app.listen(3000);
}
bootstrap();

addBlog method


  @Put()
  @UseInterceptors(FileInterceptor('thumbnail', { storage: BlogStorage }))
  addBlog(@UploadedFile() file, @Body() addBlogModel: AddBlogModel) {
    console.log(file);
  }

add-blog.model.ts

import { IsArray, IsBoolean, IsNotEmpty, IsOptional, IsString, Length } from 'class-validator';
import { Expose } from 'class-transformer';

export class AddBlogModel {
  @IsNotEmpty()
  @IsString()
  title: string;

  @IsString()
  @Length(10, 225)
  @IsOptional()
  introduction: string;

  @IsNotEmpty()
  @IsString()
  content: string;

  @IsBoolean()
  @Expose({name: 'is_published'})
  isPublished: boolean;

  @IsArray()
  @IsNotEmpty()
  tags: string[];

  @IsString()
  @IsNotEmpty()
  category: string;
}

index.hbs

<!DOCTYPE html>
<html>
<head>

</head>

<body>
<form id="form">
    <input name="title" id="title"/>
    <input name="content" id="content"/>
    <input type="file" name="thumbnail" id="thumbnail"/>

    <button type="submit">Submit</button>
</form>

<script src="https://code.jquery./jquery.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/axios/0.19.0/axios.min.js"></script>
<script type="text/javascript">
    $(document).ready(function () {
        $("#form").on('submit', function (e) {
            e.preventDefault();
            const data = $(this).serializeArray()
            const data_from_array = {}
            var formData = new FormData()

            $.map(data, function(n, i){
                formData.append(n['name'], n['value'])
            });

            const file = $('input[type="file"]')[0].files[0]

            formData.append('thumbnail', file)

            const config = {
                headers: {
                    'content-type': 'multipart/form-data'
                }
            }
            axios.put('http://localhost:3000/blogs', formData, config).then(res => {
                console.log(res)
            }).catch(err => {
                console.log(err.response)
            })
        });
    })
</script>
</body>
</html>

I expect the file is not uploaded if the validation is failed.

Share Improve this question edited Oct 20, 2019 at 20:53 Rentaro Alshreef asked Oct 20, 2019 at 20:38 Rentaro AlshreefRentaro Alshreef 731 silver badge4 bronze badges 2
  • Please show the UploadedFile decorator as well. – Thomas Commented Oct 20, 2019 at 21:00
  • @Thomas thanx for the response, the UploadedFile decorator is exported from Nestjs framework. github./nestjs/nest/blob/master/packages/mon/decorators/… FileInterceptor() decorator is exported from @nestjs/platform-express package while @UploadedFile() from @nestjs/mon. – Rentaro Alshreef Commented Oct 20, 2019 at 21:11
Add a ment  | 

1 Answer 1

Reset to default 4

What's happening here has to do with the Execution order of the NestJS Request Cycle, namely, how interceptors are called and fired before pipes are. In this case, you are calling the file upload interceptor, letting that code run as needed, and then validating your payload, so even if you have an invalid payload you are still uploading the file. You can view the file upload interceptor here and see what that code looks like. If you absolutely need the file upload and payload to be in the same request, you could always create your own validation interceptor instead of pipe and run this validation before the file upload interceptor. Otherwise you can make them two separate requests.

发布评论

评论列表(0)

  1. 暂无评论