我正在尝试在我的Restful Spring Boot应用程序中实现pdf文件上传。
我有以下方法;
@RequestMapping(value = FILE_URL, method = RequestMethod.POST)
public ResponseDTO submitPDF(
@ModelAttribute("file") FileDTO file) {
MediaType mediaType = MediaType.parseMediaType(file.getFile().getContentType());
System.out.println(file.getFile().getContentType());
System.out.println(mediaType);
System.out.println(mediaType.getType());
if(!"application/pdf".equals(mediaType.getType())) {
throw new IllegalArgumentException("Incorrect file type, PDF required.");
}
... more code here ...
}
FileDTO只是MultipartFile的包装器。
我然后使用邮差发送请求与form-data
体'file'=<filename.pdf>
上面printlns中的内容类型总是8字节流。无论我发送什么类型的文件(png, pdf等),它总是八字节流。如果我特别将application/pdf
设置为Postman中的内容类型头,则FileDTO中的MultipartFile最终为空。
问题是,我的弹簧控制器方法是否有问题,或者请求只是没有被邮差正确构建?
如果邮差不能得到内容类型正确,我可以期望实际的客户端应用程序正确地设置内容类型为pdf吗?
您是否尝试过Apache Tika库来检测上传文件的mime类型?
Kotlin代码示例
private fun getMimeType(file: File) = Tika().detect(file)
FileDTO
将包装multipart/form-data
的整个内容,所以如果您上传的文件输入名为file
,您的DTO/Form/POJO应该类似于:
class FileDTO{
@NotNull
private String anotherAttribute;
@NotNull
private MultipartFile file;
//Getters and Setters
}
因此你也应该将你的控制器功能更改为
@RequestMapping(value = FILE_URL, method = RequestMethod.POST)
public ResponseDTO submitPDF(@ModelAttribute FileDTO fileWrapper) {
MediaType mediaType = MediaType.parseMediaType(fileWrapper.getFile().getContentType());
System.out.println(fileWrapper.getFile().getContentType());
System.out.println(mediaType);
System.out.println(mediaType.getType());
if(!"application/pdf".equals(mediaType.getType())) {
throw new IllegalArgumentException("Incorrect file type, PDF required.");
}
... more code here ...
}
要使用这种函数,您应该在MVC配置文件中使用StandardServletMultipartResolver
。比如:@EnableWebMvc
@Configuration
@ComponentScan("mypackage.web.etc")
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
}
我希望它适合你。
通常文件上传是用MIME多部分消息格式包装的,因此HTTP头中的内容类型只能是multipart/form-data
,并且您可以在每个部分中分别指定每个字段(包括文件)的MIME类型。
在Postman中似乎没有办法为多部分字段指定MIME类型,所以我只能假设这是一个缺失的功能。
我以前有过这个问题,使用以下修复了这个问题:
Files.probeContentType(path)
返回格式类型的字符串。这似乎是我尝试过的最可靠的解决方案。