總結:Ajax上傳文件 Current request is not a multipart request 可能是jquery版本問題
作為剛上班兩周,而且還不是科班出身的小編來說,發現很多基礎不牢固,尤其記不住,所有日常問題日常重復解決,決定把問題都整理下來。最近看同事弄一個上傳圖片功能,感覺很實用,講過又不會,所以翻箱底找出來想做一個簡單版,結果copy完還是出現錯誤,Current request is not a multipart request。百思不得其解,反復試驗解決,做個記錄
上傳文件
上傳文件可以有很多種方法,也可以用插件,比如fileupload等,然而我不會,所以用的學過的form表單提交
首先添加一個form 表單,兩個input標簽,用ajax把數據傳到后台,
這里有坑注意 “processDate” 屬性為false,這個屬性的意思大概是對數據預進行序列化,是不能的。“contentType”為false 因為瀏覽器會自動設置消息頭為
multipart/form-data; boundary=----WebKitFormBoundaryAumPhHVNWRpEi4ck
如果我們自己設置成"contentType": multipart/form-data ,會報找不到什么什么邊界錯誤,以上為我理解,如有不對請指正。
后台代碼
@RestController
@RequestMapping("/file") public class FileController { @PostMapping("/upload.do") public Result uload(@RequestParam("file") MultipartFile file,HttpSession session){ // 檢查是否存在上傳文件 > file.isEmpty() if (file.isEmpty()){ // 拋出異常:文件不允許為空 return new Result("請選擇一個文件"); } //自定義的絕對路徑 String path = "C:\\Users\\chen\\Desktop\\upload"; //或者用項目的所在路徑 // String parentPath = session // .getServletContext().getRealPath("自己定一個文件夾名"); File parent = new File(path); if (!parent.exists()) { parent.mkdirs(); } // 確定文件名 > getOriginalFileName() String originalFileName = file.getOriginalFilename(); //截取上傳的文件名的后綴類型,比如.jpg int beginIndex = originalFileName.lastIndexOf("."); String suffix = originalFileName.substring(beginIndex); //隨機生成一個自己的文件名 String fileName = System.currentTimeMillis() + "" + (new Random().nextInt(90000000) + 10000000) + suffix; System.err.println(fileName); // 確定文件 File dest = new File(parent, fileName); // 執行保存文件 try { file.transferTo(dest); System.err.println("上傳完成!"); } catch (Exception e) { // 拋出異常:上傳失敗 return new Result("上傳失敗"); } // 返回 return new Result(200,"上傳成功");
按道理到現在應該是沒什么問題了,但是當運行時還是出現Current request is not a multipart request 錯誤。上網查發現自己的form表單添加了enctype=“multipart/form-data” method=“post” ,其他坑也沒踩,查看消息頭發現
瀏覽器並沒有給我們設置好,網上可不是這么說的啊!再與之前的頁面移過來進行實驗后比對后我發現了問題所在居然是
這是我們寫的
這是原來的
對沒錯,就是jq的版本不同,我吧版本換成1.9.1之后馬上就能用了。
這才是正確的請求頭。控制台打樁獲取名稱及后綴得到
可以看出已經成功,在桌面上也出現了文件夾和圖片
理論上這個方法是可以上傳任何文件的 好像是轉化成的二進制進行進行傳送(這塊我也不知道…) ,也可以在后台進行大小和格式的判斷限制
/** * 上傳文件的最大大小 */ private static final long FILE_MAX_SIZE = 5 * 1024 * 1024; /** * 允許上傳的文件類型 */ private static final List<String> FILE_CONTENT_TYPES = new ArrayList<>(); /** * 初始化允許上傳的文件類型的集合 */ static { FILE_CONTENT_TYPES.add("image/jpeg"); FILE_CONTENT_TYPES.add("image/png"); } @PostMapping("/upload.do") public Result uload(@RequestParam("file") MultipartFile file,HttpSession session){ // TODO 檢查文件大小 > file.getSize() if (file.getSize() > FILE_MAX_SIZE) { // 拋出異常:文件大小超出限制 } // TODO 檢查文件類型 > file.getContentType() if (!FILE_CONTENT_TYPES.contains( file.getContentType())) { // 拋出異常:文件類型限制 }
下面總結一下網上查到的用這種方法和報這個錯誤的原因
- form表單沒有設置 enctype=“multipart/form-data” method=“post”
- ajax的話也設為post方式
- 用ajax的話 要有
- meta http-equiv=“Content-Type” content=“multipart/form-data; charset=utf-8” 這個頭
- ajax上面說的兩個屬性要為 false
- 用百度的ueditor插件 ueditor.all.js和ueditor.all.min.js里面把post請求的Content-Type:multipart/form-data二進制傳送方式變成了Content-Type:text/html。
- 據說還有坑是用MultipartFile 需要有
- 這個jar包
- 還有說要這兩個依賴
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
還有在spring-mvc.xml 加上一句話
<!-- 設置上傳文件最大值 1M=1*1024*1024(B)=1048576 bytes -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1048576" />
</bean>
本人是spring boot框架 在application.properties 里有
# 上傳文件總的最大值
spring.servlet.multipart.max-request-size=10MB
# 單個文件的最大值
spring.servlet.multipart.max-file-size=10MB
不過發現刪了也能運行 ,也是沒搞懂。大體就這些
追加
new FormData() 與 $form.serializeArray() 都是表單序列化 但是后者是表單數據序列化 ,有興趣可以查查研究一下。