英文:
Spring boot - method 'POST' is not supported (multipart/form-data)
问题
我正在尝试通过multipart/form-data
从我的产品控制器发送POST请求,在这个请求中,我上传了图像文件和产品信息的JSON数据。
在我的Postman中,我像这样发送请求,并且收到了405错误。
在我的控制台中,我收到了以下错误信息:
"Request method 'POST' is not supported."
我不明白为什么会出现这个错误,因为我已经使用@PostMapping
注解定义了POST请求。
在Postman中更新的错误信息如下:
{
"cause": null,
"stackTrace": [
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "from",
"fileName": "UnrecognizedPropertyException.java",
"lineNumber": 61,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException"
},
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "handleUnknownProperty",
"fileName": "DeserializationContext.java",
"lineNumber": 1132,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.DeserializationContext"
},
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "handleUnknownProperty",
"fileName": "StdDeserializer.java",
"lineNumber": 2202,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.deser.std.StdDeserializer"
}, ...
希望这些信息有助于解决你的问题。如果你需要进一步的帮助,请告诉我。
英文:
I'm trying to send through multipart/form-data a post request from my products controller, where I upload a file of images and information of my product in json
@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping("/product")
public class ProductController {
final ProductService productService;
final CategoryService categoryService;
final ProductMapper productMapper;
final S3Client s3Client;
private final String BUCKET_NAME = "awstockproducts" + System.currentTimeMillis();
public ProductController(ProductService productService, ProductMapper productMapper, CategoryService categoryService, S3Client s3Client) {
this.productService = productService;
this.productMapper = productMapper;
this.categoryService = categoryService;
this.s3Client = s3Client;
}
@PostMapping(MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> saveProduct (@RequestPart("productDto") @Valid ProductDto productDto, @RequestPart(value = "file")MultipartFile file) {
try {
if (productService.existsByProduct(productDto.getProduct())) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("Product already exists!");
}
ProductModel productModel = productMapper.toProductModel(productDto);
CategoryModel categoryModel = categoryService.findById(productDto.getProductCategory().getCategory_id())
.orElseThrow(() -> new RuntimeException("Category not found"));
productModel.setProductCategory(categoryModel);
String fileName = "/products/images/" + UUID.randomUUID().toString() + "-" + file.getOriginalFilename();
s3Client.putObject(PutObjectRequest
.builder()
.bucket(BUCKET_NAME)
.key(fileName)
.build(),
software.amazon.awssdk.core.sync.RequestBody.fromString("Testing java sdk"));
return ResponseEntity.status(HttpStatus.CREATED).body(productService.save(productModel));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.CONFLICT).body("Cannot create product. Check if the fields sent in your request are correct.");
}
}
in my postman I'm sending it like this, and getting the error 405
In my console I am getting the error:
Request method 'POST' is not supported]
I don't understand why since I am sending a postMapping
updated error in postman:
{
"cause": null,
"stackTrace": [
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "from",
"fileName": "UnrecognizedPropertyException.java",
"lineNumber": 61,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException"
},
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "handleUnknownProperty",
"fileName": "DeserializationContext.java",
"lineNumber": 1132,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.DeserializationContext"
},
{
"classLoaderName": "app",
"moduleName": null,
"moduleVersion": null,
"methodName": "handleUnknownProperty",
"fileName": "StdDeserializer.java",
"lineNumber": 2202,
"nativeMethod": false,
"className": "com.fasterxml.jackson.databind.deser.std.StdDeserializer"
}, ...
答案1
得分: 0
更改您的@PostMapping(MediaType.MULTIPART_FORM_DATA_VALUE)
,因为在那里放置媒体类型实际上会将URL映射到/product/multipart/form-data
而不是/product/
。
将其更改为:
@PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
此外,您需要更新方法签名,类似于以下内容(将@RequestPart更改为@RequestParam):
@PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> saveProduct(@RequestParam("productDto") String jsonString, @RequestParam("file") MultipartFile file) {
ObjectMapper objectMapper = new ObjectMapper();
ProductDto productDto = objectMapper.readValue(jsonString, ProductDto.class);
}
确保您具有相关的依赖项commons-fileupload
和commons-io
。
此外,我建议在上传时设置文件的最大上传大小,可以像这样实现:
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(1024 * 1024 * 5); // 5 MB
return resolver;
}
然后,在Postman中调用http://localhost:8078/product/
。
另一种解决方案是在Spring中创建适当的转换器:
public class ProductDtoConverter extends AbstractHttpMessageConverter<ProductDto> {
public ProductDtoConverter() {
super(MediaType.APPLICATION_JSON);
}
@Override
protected boolean supports(Class<?> clazz) {
return ProductDto.class.isAssignableFrom(clazz);
}
@Override
protected ProductDto readInternal(Class<? extends ProductDto> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
String productDtoString = IOUtils.toString(inputMessage.getBody(), StandardCharsets.UTF_8);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(productDtoString, ProductDto.class);
}
}
然后,在您的AppConfig
中:
@Configuration
public class AppConfig {
@Bean
public ProductDtoConverter productDtoConverter() {
return new ProductDtoConverter();
}
}
英文:
Change your @PostMapping(MediaType.MULTIPART_FORM_DATA_VALUE)
because putting the media type there will actually map the URL to /product/multipart/form-data
and not /product/
change it to this
@PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
also, you need to update the method signature to something like this (Change @RequestPart to @RequestParam)
@PostMapping(value = "/", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<Object> saveProduct (@RequestParam("productDto") String jsonString, @RequestParam("file") MultipartFile file) {
ObjectMapper objectMapper = new ObjectMapper();
ProductDto productDto = objectMapper.readValue(jsonString, ProductDto.class);
}
and make sure you have the relevant dependencies commons-fileupload and commons-io
also I recomemend when Uploading set a maximum upload size for the file you can do it like this:
@Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(1024 * 1024 * 5); // 5 MB
return resolver;
}
and then in postman call http://localhost:8078/product/
A second solution you can create the suitable converter in Spring:
the solution is like
public class ProductDtoConverter extends AbstractHttpMessageConverter<ProductDto> {
public ProductDtoConverter() {
super(MediaType.APPLICATION_JSON);
}
@Override
protected boolean supports(Class<?> clazz) {
return ProductDto.class.isAssignableFrom(clazz);
}
@Override
protected ProductDto readInternal(Class<? extends ProductDto> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
String productDtoString = IOUtils.toString(inputMessage.getBody(), StandardCharsets.UTF_8);
ObjectMapper objectMapper = new ObjectMapper();
return objectMapper.readValue(productDtoString, ProductDto.class);
}
}
and in you AppConfig:
@Configuration
public class AppConfig {
@Bean
public ProductDtoConverter productDtoConverter() {
return new ProductDtoConverter();
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论