SpringMVC(14) - spring的多部件(文件上傳)支持

參考:https://docs.spring.io/spring/docs/4.3.20.RELEASE/spring-framework-reference/htmlsingle/#mvc-multipart

 

1. 簡介
Spring的內置多部件支持處理Web應用程序中的文件上傳。可以使用org.springframework.web.multipart包中定義的可插入的MultipartResolver對象啓用此多部件支持。 Spring提供了一個用於Commons FileUpload的MultipartResolver實現,另一個用於Servlet 3.0多部件請求解析。

默認情況下,Spring不進行多部件處理,因爲一些開發人員希望自己處理多部件。可以通過向Web應用程序的上下文添加多部件解析器來啓用Spring多部件處理。檢查每個請求以查看它是否包含多部件。如果未找到任何多部件,則請求將按預期繼續執行。如果在請求中找到了多部件,則將會使用已在上下文中聲明的MultipartResolver。之後,請求中的multipart屬性將被視爲任意其他屬性。

 

2. 將MultipartResolver與Commons FileUpload一起使用
以下示例顯示如何使用CommonsMultipartResolver:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <!-- 最大文件大小,單位字節 -->
    <property name="maxUploadSize" value="100000"/>
</bean>

當然,還需要在類路徑中放置適當的jar,以使多部件解析器工作。對於CommonsMultipartResolver,需要使用commons-fileupload.jar。

當Spring DispatcherServlet檢測到多部件請求時,它會激活已在上下文中聲明的解析器並移交請求。解析器然後將當前的HttpServletRequest包裝到支持多部分文件上傳的MultipartHttpServletRequest中。使用MultipartHttpServletRequest,可以獲取有關此請求包含的多部件的信息,並實際訪問控制器中的多部件文件。

 

3. 將MultipartResolver與Servlet 3.0一起使用
爲了使用基於Servlet 3.0的多部件解析,需要在web.xml中使用“multipart-config”部分標記DispatcherServlet,或在Servlet中通過代碼方式使用javax.servlet.MultipartConfigElement註冊,或者在自定義Servlet的類上有一個javax.servlet.annotation.MultipartConfig註解。由於Servlet 3.0不允許從MultipartResolver完成這些設置,因此需要在該Servlet註冊級別應用配置設置(如最大大小或存儲位置)。

一旦以上述方式之一啓用了Servlet 3.0多部件解析,就可以將StandardServletMultipartResolver添加到Spring配置中:

<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver">
</bean>

 

4. 處理表單中的文件上傳
MultipartResolver完成其任務後,將像處理其他任何請求一樣處理該請求。 首先,創建一個帶有文件輸入的表單,允許用戶上傳表單。 encoding屬性(enctype="multipart/form-data")讓瀏覽器知道如何將表單編碼爲multipart請求:

<html>
    <head>
        <title>Upload a file please</title>
    </head>
    <body>
        <h1>Please upload a file</h1>
        <form method="post" action="/form" enctype="multipart/form-data">
            <input type="text" name="name"/>
            <input type="file" name="file"/>
            <input type="submit"/>
        </form>
    </body>
</html>

下一步是創建一個處理文件上傳的控制器。 這個控制器非常類似於普通的帶註解的@Controller,除了我們在方法參數中使用MultipartHttpServletRequest或MultipartFile:

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") MultipartFile file) {

        if (!file.isEmpty()) {
            byte[] bytes = file.getBytes();
            // 將bytes存儲在某處,如數據庫,本地文件
            return "redirect:uploadSuccess";
        }

        return "redirect:uploadFailure";
    }

}

注意@RequestParam方法參數如何映射到表單中聲明的輸入元素。 在此示例中,byte[]沒有任何操作,但實際上可以將其保存在數據庫中,將其存儲在文件系統中,等等。

使用Servlet 3.0多部件解析時,還可以使用javax.servlet.http.Part作爲方法參數:

@Controller
public class FileUploadController {

    @PostMapping("/form")
    public String handleFormUpload(@RequestParam("name") String name, @RequestParam("file") Part file) {

        InputStream inputStream = file.getInputStream();
        // store bytes from uploaded file somewhere

        return "redirect:uploadSuccess";
    }

}

 

5. 處理程序客戶端的文件上傳請求
還可以在RESTful服務方案中從非瀏覽器客戶端提交多部件請求。所有上述示例和配置也適用於此處。但是,與通常提交文件和簡單表單字段的瀏覽器不同,編程客戶端還可以發送特定內容類型的更復雜數據 --- 例如,帶有文件的多部件請求和帶有JSON格式數據的第二部分:

POST /someUrl
Content-Type: multipart/mixed

--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="meta-data"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{
    "name": "value"
}
--edt7Tfrdusa7r3lNQc79vXuhIIMlatb7PQg7Vp
Content-Disposition: form-data; name="file-data"; filename="file.properties"
Content-Type: text/xml
Content-Transfer-Encoding: 8bit
... File Data ...

可以使用 @RequestParam("meta-data") String metadata 控制器方法參數訪問名爲“meta-data”的部分。但是,可能更願意接受從請求部分體中的JSON格式數據初始化強類型對象,這與@RequestBody藉助一個HttpMessageConverter將非多部件請求體轉換爲目標對象的方式非常相似。

爲此,可以使用@RequestPart註解而不是@RequestParam註解。它允許通過HttpMessageConverter傳遞特定多部件的內容,同時考慮到multipart的'Content-Type'頭:

@PostMapping("/someUrl")
public String onSubmit(@RequestPart("meta-data") MetaData metadata, @RequestPart("file-data") MultipartFile file) {
    // ...
}

請注意如何使用@RequestParam或@RequestPart可以互換地訪問MultipartFile方法參數。 但是,本案例中的@RequestPart("meta-data") MetaData 方法參數基於其“Content-Type”頭讀取爲JSON內容,並在MappingJackson2HttpMessageConverter的幫助下進行轉換。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章