最近学习SpringBoot时,使用jquery uploadify/uploadifive 插件进行图片上传时碰到一坑,在此记录下。解决方案看最后。
问题描述:页面使用普通form提交方式后台可以正确无误获得到图片,但是使用uploadify组件时则总是抛出异常:
Resolved exception caused by Handler execution: org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file_upload' is not present
使用Form可以正常提交和返回的图片页面:
Image Upload
后台响应的Spring代码:
package com.my.controller; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; /** * Description: To do *
* Author : Adore Chen * Created: 2018-08-23 */ @Controller public class FileUploadController { private Logger logger = LoggerFactory.getLogger(getClass()); // save uploaded file to this folder private String uploadDir = System.getProperty("user.home") + "/upload/"; public FileUploadController(){ File dir = new File(uploadDir); if(!dir.exists()){ dir.mkdirs(); } } @RequestMapping(value = "/upload", method = RequestMethod.POST) public String upload(@RequestParam("file_upload") MultipartFile file, ModelMap modelMap) { modelMap.addAttribute("image", file); // Save file on system if (!file.isEmpty()) { try{ Path path = Paths.get(uploadDir + file.getOriginalFilename()); Files.write(path, file.getBytes()); logger.info("write file to: {}", path); }catch (Exception e){ logger.error("upload file error", e); } } return "searchResult"; } }
Application代码如下:
package com.my.controller; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.web.multipart.support.StandardServletMultipartResolver; import org.springframework.web.servlet.view.InternalResourceViewResolver; import org.springframework.web.servlet.view.JstlView; import javax.servlet.MultipartConfigElement; /** * Description: To do *
* Author : Adore Chen * Created: 2018-08-23 */ @SpringBootApplication public class Application { private int MAX_UPLOAD_SIZE = 5 * 1024 * 1024; public static void main(String[] args){ SpringApplication.run(Application.class, args); } @Bean public CommandLineRunner commandLineRunner(ApplicationContext applicationContext){ return args -> { System.out.println("Picture Search Application Started ... ===>"); }; } @Bean MultipartConfigElement multipartConfigElement() { return new MultipartConfigElement(System.getProperty("java.io.tmpdir"), MAX_UPLOAD_SIZE, MAX_UPLOAD_SIZE * 2, MAX_UPLOAD_SIZE / 2); } @Bean public StandardServletMultipartResolver multipartResolver() { return new StandardServletMultipartResolver(); } }
页面使用form按钮太多,不方便布局,于是准备使用js框架上传文件。jquery.file_upload组件功能强大,但是文档和使用太复杂,不想读他们大片大片的文档,于是选择了简洁的jquery uploadify框架。
uploadify flash版,免费版,现在很多主流浏览器firefox/safri都不支持flash了,chrome默认也是关闭的。
uploadifive html5版,支持主流浏览器,收费版;(推荐使用,给他们打个广告)。
使用uploadifive文件上传的页面:[官方文档demo版-稍微修改]
UploadiFive Test Uploadify Demo
然后上传到后端就抛出异常:
MissingServletRequestPartException: Required request part 'file_upload' is not present
想了很久都没有找到原因, 经过前面form页面可以正确上传排除了后端代码有问题的可能,那么确实是后端抛出的异常,第一个反应就是input标签的name没有设置对,检查了发现没有任何问题,就是file_upload,有点蒙了。
最后怀疑uploadifive组件可能提交数据格式有问题,于是把chrome develop tool调出来发现看不了request的数据(问了度娘未果,后来发现要点击filter选择all就有了),真是坑啊。还是使用firefox吧,这个好用。
分析提交到后的数据如下:
------WebKitFormBoundaryp8SORXOshiJc12is Content-Disposition: form-data; name="Filedata"; filename="WechatIMG38.jpeg" Content-Type: image/jpeg ------WebKitFormBoundaryp8SORXOshiJc12is--
看到name=“Filedata”这项顿时明白为什么了,明明我的input name=file_upload, uploadifive却把他写成Filedata不报错才怪。
以前uploadify早期版本挺好用的啊,没有这个坑的,新收费的版本居然还有这么一坑。它给的demo文档又不说,浪费很多时间。
慢慢读它的文档,发现提供了fileObj 属性定制upload file name,不给默认 Filedata。(MD,真是大坑,有这么默认的吗?)
fileObjName
Input TypeString
Default Value'Filedata'
The name of the file object to use in your server-side script. For example, in PHP, if this option is set to ‘the_files’, you can access the files that have been uploaded using $_FILES[‘the_files’];
修改js代码,添加属性fileObjName,解决问题。
$(function() { $('#file_upload').uploadifive({ 'fileObjName' : 'file_upload', 'uploadScript' : '/upload' // Put your options here }); });
参考文献:
http://www.uploadify.com/documentation/uploadifive/implementing-uploadifive/
http://www.uploadify.com/documentation/uploadifive/fileobjname-2/
https://www.cnblogs.com/magicalSam/p/7189476.html
https://www.cnblogs.com/smiler/p/6857167.html
源代码下载:
https://github.com/adorechen/uploadify_demo