问题
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/common';
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.com/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/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.
回答1:
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.
回答2:
Had the same problem, what I ended up doing was manually validating the field before calling my service,
Implementing an interceptor just to validate the file seems overkill.
async createUser(@Response() res, @UploadedFile() avatar, @Body() user: CreateUserDTO) {
// FileUploads are not validated in the Pipe
if (_.isNil(avatar)) {
throw new BadRequestException(['avatar photo is required'], 'Validation Failed');
}
来源:https://stackoverflow.com/questions/58477104/nestjs-image-uploaded-even-if-body-validation-fails