1. 程式人生 > 其它 >Spring MVC 上傳檔案(處理multipart型別資料)

Spring MVC 上傳檔案(處理multipart型別資料)

技術標籤:springmvcjava

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>

五、測試執行
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述