Spring MVC 上傳檔案(處理multipart型別資料)
web應用中有很多上傳檔案或者圖片的業務。那麼這種業務在Springmvc中是如何實現的呢?本篇文章就講述了在SpringMVC中如何實現檔案上傳功能。
一、multipart請求
檔案上傳在底層其實就是前端form表單提交enctype="multipart/form-data"
型別的資料。那麼首先就來介紹一下multipart請求。
我們傳統的from表單提交的都是文字型別的資料,比如登錄檔,當提交表單的時候,這些屬性會key=value的形式拼接成字串傳送到後端
firstName=Charles&lastName=Xavier&email=professorx%40xmen.org&username=professorx&password=letmein01
這種處理方式很簡單也很有效,但是對於圖片、視訊等二進位制資料就不能這麼處理了,這裡就要用到multipart表單了。multipart表單和上面介紹的普通表單不同,它會把表單分割成塊,表單中的每個欄位對應一個塊,每個塊都有自己的資料型別。也就是說,對於上傳欄位對應的塊,它的資料型別就可以是二進位制了:
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“firstName”
Charles
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“lastName”Xavier
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“email”
[email protected]
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“username”
professorx
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“password”letmein01
------WebKitFormBoundaryqgkaBn8IHJCuNmiW
Content-Disposition: form-data; name=“profilePicture”; filename=“me.jpg”
Content-Type: image/jpeg
[[ Binary image data goes here ]]
------WebKitFormBoundaryqgkaBn8IHJCuNmiW–
在上面這個請求就是mutipart 請求,最後一個欄位profilePicture有自己的Content-Type,值是image/jpeg,而其它欄位都是簡單的文字型別。
雖然mutipart請求看起來比較複雜,但是在spring mvc中處理起來是非常簡單的。在寫我們處理上傳檔案的controller之前,我們得先配置一個Mutipart Resolver來告訴DispatchServlet如何解析一個mutipart 請求。
二、配置multipartResolver
實現檔案上傳,其實就是解析一個Mutipart
請求。DispatchServlet
自己並不負責去解析mutipart 請求,而是委託一個實現了MultipartResolver
介面的類來解析mutipart請求。在Spring3.1之後Spring提供了兩個現成的MultipartResolver
介面的實現類:
CommonMutipartResolver
:通過利用Jakarta Commons FileUpload
來解析mutipart 請求StandardServletMutipartResolver
:依賴Servlet3.0
來解析mutipart請求
方式一:CommonMutipartResolver方式實現
- 在pom檔案中引入座標
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
- 在Springmvc的配置檔案中配置multipartResolver
<!--註冊檔案上傳解析器-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="1024000000"></property>
</bean>
其中id="multipartResolver"
必須配置,如果不配置Springmvc在對multipart型別的資料處理時會丟擲下邊的異常:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: 由於沒有提供multi-part配置,無法處理parts
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909)
javax.servlet.http.HttpServlet.service(HttpServlet.java:652)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
javax.servlet.http.HttpServlet.service(HttpServlet.java:733)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
方式二:StandardServletMutipartResolver
- 配置multipartResolver
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
- 配置servlet初始化引數
<multipart-config>
<location>/tmp/spittr/uploads</location>
<max-file-size>2097152</max-file-size>
<max-request-size>4194304</max-request-size>
</multipart-config>
mutipart-config
裡面有三個配置項:
location
:上傳檔案用到的臨時資料夾,是一個絕對路徑,需要注意,這個屬性是必填的
max-file-size
:上傳檔案的最大值,單位是byte,預設沒有限制
max-request-size
:整個mutipart請求的最大值,單位是byte,預設沒有限制
三、實現相應的Controller
@Controller
@RequestMapping("/upload")
public class UploadFileController {
@RequestMapping(method = RequestMethod.POST)
public ModelAndView handle12(MultipartFile uploadFile, HttpServletRequest request) throws IOException {
//取得原檔名的副檔名
String originalFilename = uploadFile.getOriginalFilename();
String substring = originalFilename.substring(originalFilename.lastIndexOf(".") + 1, originalFilename.length());
//得到新的檔名
String newFileName = UUID.randomUUID() + "."+substring;
//取得新的檔名的儲存路徑
String realPath =
request.getSession().getServletContext().getRealPath("/uploads");
//在指定目錄下建立新的檔案
String datePath = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
File flooder = new File(realPath + "/" + datePath);
if(!flooder.exists()) {
flooder.mkdirs();
}
uploadFile.transferTo(new File(flooder,newFileName));
//將資料返回給前臺介面
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("success");
//返回執行成功頁面
return modelAndView;
}
}
四、編寫jsp介面,其中enctype
必須設定為multipart/form-data
<%--
1 method="post"
2 enctype="multipart/form-data"
3 type="file"
--%>
<form method="post" enctype="multipart/form-data" action="/spring_demo_war_exploded/upload">
<input type="file" name="uploadFile"/>
<input type="submit" value="上傳"/>
</form>
五、測試執行