我正在尝试将产品和产品图像从Angular 7前端发送到SpringMVC后端。 为了添加对多部分文件的支持,我在我的应用程序配置中添加了这个 bean。
@Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(1000000);
return multipartResolver;
}
由于我想在控制器中单独接收 Product 对象,因此我使用 @RequestPart 分别获取两者,如下所示:
@RequestMapping(value = "save", method = RequestMethod.POST)
public ResponseEntity addProduct(@Valid @RequestPart Product product, @RequestPart MultipartFile[] images, BindingResult bindingResult, HttpServletRequest
}
在前端,我将图像添加到 FormData,如下所示:
let formData = new FormData();
formData.append('product', new Blob([JSON.stringify(this.product)],{ type: "application/json" }));
// I iterate and append all the images like this
formData.append('image[]', this.images, this.images.name);
this.http.post(this.appService.getApiUrl() + "api/product/save/", product);
问题是,每当我提交表单时,我都会收到此异常作为响应:HTTP 状态 415 – 不支持的媒体类型。 我尝试通过在CommonsMultipartResolver类中设置断点来调试此问题,并且在通过代码跟踪请求后,我发现当调用getSupportedMediaTypes()时,它只返回两种媒体类型:
- 应用程序/JSON
- 应用程序/*+JSON
在AbstractHttpMessageConverter中的以下方法中:
protected boolean canRead(@Nullable MediaType mediaType) {
if (mediaType == null) {
return true;
} else {
Iterator var2 = this.getSupportedMediaTypes().iterator();
MediaType supportedMediaType;
do {
if (!var2.hasNext()) {
return false;
}
supportedMediaType = (MediaType)var2.next();
} while(!supportedMediaType.includes(mediaType));
return true;
}
}
找到这个,我尝试在 AppConfig 中添加这样的MediaType.MULTIPART_FORM_DATA
:
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
List<MediaType> types = new ArrayList<>();
types.add(MediaType.APPLICATION_JSON);
types.add(MediaType.APPLICATION_JSON_UTF8);
types.add(MediaType.MULTIPART_FORM_DATA);
((MappingJackson2HttpMessageConverter) converter).setSupportedMediaTypes(types);
Hibernate5Module hibernate5Module = new Hibernate5Module();
hibernate5Module.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
ObjectMapper mapper = ((MappingJackson2HttpMessageConverter) converter).getObjectMapper();
mapper.registerModule(hibernate5Module);
}
}
}
但它仍然行不通。当应用程序启动时,我确实看到AbstractJackson2HttpMessageConverter的构造函数被我的MediaType调用,但它们被更多对同一构造函数的调用覆盖。 有什么方法可以让媒体类型持久化吗?我可能看错了方向,所以任何见解都会有所帮助。
类路径上需要杰克逊库。Spring 默认情况下不会声明这一点。确保在 Spring MVC 应用程序的类路径中至少有com.fasterxml.jackson.core:jackson-databind
可用。Apache Maven的例子:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
jackson.version
值的示例:2.9.0
1)您需要提供服务器端支持的输入数据。由于您正在发送文件,这意味着服务器正在使用多部分数据。 对于多部分,我们需要设置消耗 = "多部分/表单数据">
@RequestMapping(value = "save", method = RequestMethod.POST, consumes = "multipart/form-data")
public ResponseEntity addProduct(@Valid @RequestPart Product product, @RequestPart MultipartFile[] images, BindingResult bindingResult, HttpServletRequest
}
2)由于表单正在发送多部分数据,因此我们也需要在post调用的http标头中在前端设置内容类型。内容类型:多部分/表单数据">