一、簡述
一個javaWeb項目中,文件上傳功能幾乎是必不可少的,本人在項目開發中也時常會遇到,以前也沒怎么去理它,今天有空學習了一下這方面的知識,于是便將本人學到的SpringMVC中單文件與多文件上傳這部分知識做下筆記。
二、單文件上傳
1、頁面
這里以一個簡單的表單提交為例子,文件上傳需要將表單的提交方法設置為post,將enctype的值設置為"multipart/form-data"。
1
2
3
4
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > < input type = "file" name = "img" >< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
在Controller的處理方法中,使用MultipartFile對象作為參數接收前端上傳過來的文件,具體說明請看代碼注釋。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) // 這里的MultipartFile對象變量名跟表單中的file類型的input標簽的name相同,所以框架會自動用MultipartFile對象來接收上傳過來的文件,當然也可以使用@RequestParam("img")指定其對應的參數名稱 public String upload(MultipartFile img, HttpSession session) throws Exception { // 如果沒有文件上傳,MultipartFile也不會為null,可以通過調用getSize()方法獲取文件的大小來判斷是否有上傳文件 if (img.getSize() > 0 ) { // 得到項目在服務器的真實根路徑,如:/home/tomcat/webapp/項目名/images String path = session.getServletContext().getRealPath( "images" ); // 得到文件的原始名稱,如:美女.png String fileName = img.getOriginalFilename(); // 通過文件的原始名稱,可以對上傳文件類型做限制,如:只能上傳jpg和png的圖片文件 if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); return "/success.jsp" ; } } return "/error.jsp" ; } } |
3、springmvc.xml配置
使用MultipartFile對象接收前端上傳過來的文件,還需要在springmvc的配置文件中進行如下配置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" xmlns:mvc = "http://www.springframework.org/schema/mvc" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:aop = "http://www.springframework.org/schema/aop" xmlns:tx = "http://www.springframework.org/schema/tx" xmlns:context = "http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> ... <!-- 注意:CommonsMultipartResolver的id是固定不變的,一定是multipartResolver,不可修改 --> < bean id = "multipartResolver" class = "org.springframework.web.multipart.commons.CommonsMultipartResolver" > <!-- 如果上傳后出現文件名中文亂碼可以使用該屬性解決 --> < property name = "defaultEncoding" value = "utf-8" /> <!-- 單位是字節,不設置默認不限制總的上傳文件大小,這里設置總的上傳文件大小不超過1M(1*1024*1024) --> < property name = "maxUploadSize" value = "1048576" /> <!-- 跟maxUploadSize差不多,不過maxUploadSizePerFile是限制每個上傳文件的大小,而maxUploadSize是限制總的上傳文件大小 --> < property name = "maxUploadSizePerFile" value = "1048576" /> </ bean > <!-- 設置一個簡單的異常解析器,當文件上傳超過大小限制時跳轉 --> < bean class = "org.springframework.web.servlet.handler.SimpleMappingExceptionResolver" > < property name = "defaultErrorView" value = "/error.jsp" /> </ bean > </ beans > |
上面配置文件中的CommonsMultipartResolver下的屬性值配置不是必須的,你也可以全部不寫。到這里就可以實現單個文件上傳了,下面來看看多文件上傳。
三、多文件上傳
其實多文件上傳也很簡單,單文件上傳是在Controller的處理方法中使用MultipartFile對象作為參數接收前端上傳過來的文件,而多文件上傳則使用MultipartFile對象數組來接收。
1、頁面
該頁面中有幾個name值一樣的file類型的input標簽,其他跟單文件上傳的頁面沒差。
1
2
3
4
5
6
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > file 1 : < input type = "file" name = "imgs" >< br /> file 2 : < input type = "file" name = "imgs" >< br /> file 3 : < input type = "file" name = "imgs" >< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
控制器中的處理方法使用MultipartFile[]數組作為接收參數,并不能直接使用,需要校正參數,具體說明請看代碼注釋。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) // 這里的MultipartFile[] imgs表示前端頁面上傳過來的多個文件,imgs對應頁面中多個file類型的input標簽的name,但框架只會將一個文件封裝進一個MultipartFile對象, // 并不會將多個文件封裝進一個MultipartFile[]數組,直接使用會報[Lorg.springframework.web.multipart.MultipartFile;.<init>()錯誤, // 所以需要用@RequestParam校正參數(參數名與MultipartFile對象名一致),當然也可以這么寫:@RequestParam("imgs") MultipartFile[] files。 public String upload( @RequestParam MultipartFile[] imgs, HttpSession session) throws Exception { for (MultipartFile img : imgs) { if (img.getSize() > 0 ) { String path = session.getServletContext().getRealPath( "images" ); String fileName = img.getOriginalFilename(); if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); } } } return "/success.jsp" ; } } |
同樣的,使用MultipartFile數組接收前端上傳過來的多個文件,也需要在springmvc的配置文件進行配置,具體配置與上述單文件上傳的springmvc.xml配置沒差,直接拷貝過來就行。這樣,就可以進行多文件上傳了。
四、多種文件上傳情景綜合
當然,項目開發中,場景可能并不是這么簡單,上述的多文件上傳是一個個文件選擇后一起上傳(即多個name相同的input標簽),那要是我項目中只要一個input標簽就可以一次性多個文件呢?又或者一個頁面中既要一個個選擇的多文件上傳,又要一次性選擇的多文件上傳,還要有單文件上傳呢?沒問題,MultipartFile[]通吃,代碼也很easy,下面直接上代碼。
1、頁面
這里的 “一次選擇多個文件的多文件上傳” 只是在input標簽中加上了multiple屬性而已。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
< form action = "${pageContext.request.contextPath}/test/upload.do" method = "post" enctype = "multipart/form-data" > 一次選擇多個文件的多文件上傳 : < br /> < input type = "file" name = "imgs1" multiple>< br /> < br /> 一次選擇一個文件的多文件上傳 : < br /> < input type = "file" name = "imgs2" >< br /> < input type = "file" name = "imgs2" >< br />< br /> 單文件上傳 : < br /> < input type = "file" name = "imgs3" >< br />< br /> < input type = "submit" name = "提交" > </ form > |
2、控制器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
@Controller @RequestMapping ( "/test" ) public class MyController { @RequestMapping (value = "/upload.do" , method = RequestMethod.POST) public String upload( @RequestParam MultipartFile[] imgs1, @RequestParam MultipartFile[] imgs2, @RequestParam MultipartFile[] imgs3, HttpSession session) throws Exception { String path = session.getServletContext().getRealPath( "images" ); for (MultipartFile img : imgs1) { uploadFile(path, img); } for (MultipartFile img : imgs2) { uploadFile(path, img); } for (MultipartFile img : imgs3) { uploadFile(path, img); } return "/success.jsp" ; } private void uploadFile(String path, MultipartFile img) throws IOException { if (img.getSize() > 0 ) { String fileName = img.getOriginalFilename(); if (fileName.endsWith( "jpg" ) || fileName.endsWith( "png" )) { File file = new File(path, fileName); img.transferTo(file); } } } } |
MultipartFile[]就是如此強大,不管單個多個,邏輯處理一樣,所以建議在項目開發中使用MultipartFile[]作為文件的接收參數。
五、拓展
1、MultipartFile類常用的一些方法:
1
2
3
4
5
6
7
|
String getContentType() //獲取文件MIME類型 InputStream getInputStream() //獲取文件流 String getName() //獲取表單中文件組件的名字 String getOriginalFilename() //獲取上傳文件的原名 long getSize() //獲取文件的字節大小,單位byte boolean isEmpty() //是否為空 void transferTo(File dest) |
2、CommonsMultipartResolver的屬性解析
- defaultEncoding:表示用來解析request請求的默認編碼格式,當沒有指定的時候根據Servlet規范會使用默認值ISO-8859-1。當request自己指明了它的編碼格式的時候就會忽略這里指定的defaultEncoding。
- uploadTempDir:設置上傳文件時的臨時目錄,默認是Servlet容器的臨時目錄。
- maxUploadSize:設置允許上傳的總的最大文件大小,以字節為單位計算。當設為-1時表示無限制,默認是-1。
- maxUploadSizePerFile:跟maxUploadSize差不多,不過maxUploadSizePerFile是限制每個上傳文件的大小,而maxUploadSize是限制總的上傳文件大小。
- maxInMemorySize:設置在文件上傳時允許寫到內存中的最大值,以字節為單位計算,默認是10240。
- resolveLazily:為true時,啟用推遲文件解析,以便在UploadAction中捕獲文件大小異常。
六、注意
- 在開發過程中,建議把配置文件中的異常解析器(SimpleMappingExceptionResolver)先注釋掉,方便我們查看錯誤。
- 有時候上傳出錯,是因為我們在配置文件中限制了上傳文件的大小,你可以不加這個限制,但個人建議這個限制最好還是加上,具體文件大小限制請根據公司項目情況而定。
- SpringMVC中使用MultipartFile接收上傳文件需要依賴兩個jar包,分別是:commons-fileupload-1.3.3.jar、commons-io-2.5.jar。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://juejin.im/post/594b31da1b69e60062a199fa