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
1 Answer
Reset to default 4What'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.