最近家裡的網出現了莫名其妙的問題,連不上碼雲了,所以把示例遷到了 github 上。本示例見這個專案的 master 分支的 ZestMultipartController.java。
Spring 的內建 multipart 支援用於處理 Web 應用程式中的檔案上傳。你可以通過使用外掛化的MultipartResolver
物件來啟用 multipart 支援,它定義在包org.springframework.web.multipart
中。Spring 提供了一個MultipartResolver
的實現,使用了 Apache 的 Commons FileUpload 和一些其他的東西,用於對 Servlet 3.0 的 multipart 請求的解析。
預設地,Spring 不進行 multipart 處理,因為很多開發者想要自己處理。你可以通過在 Web 應用程式上下文中新增一個 multipart 解析器來啟用 Spring 的 multipart 處理。每一個請求都要被檢查,看看是否包含一個 multipart。如果沒有發現 multipart,請求就正常繼續啦;如果有的話,你在上下文中宣告的MultipartResolver
就會開始工作啦。之後嘞,你就可以像訪問其他請求屬性那樣訪問 multipart 屬性啦。
和 Commons FileUpload 一起使用MultipartResolver
下面的例子展示了怎樣使用CommonsMultipartResolver
,快來看看吧:
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 最大上傳大小,單位:位元組(byte) -->
<property name="maxUploadSize" value="100000"/>
<!-- 你也可以在這裡提供其他的屬性 -->
</bean>
當然啦,你也需要在類路徑下放上合適的 Jar 檔案來保證 multipart 解析器工作。對於上面的例子嘞,你需要使用 commons-fileupload.jar。
當 Spring 的DispatcherServlet
檢測到一個 multi-part 請求時,它會啟用你宣告好的解析器,然後把這個解析器轉交給請求。解析器會把當前的HttpServletRequest
扭曲(wrap?)為 一個支援 multipart 檔案上傳的MultipartHttpServletRequest
。使用這個MultipartHttpServletRequest
,你就可以獲取這個請求中的 multipart 的資訊了, 同時也可以在你的控制器中訪問這些 multipart 檔案。
在表單中處理檔案上傳
在MultipartResolver
完成自己的工作之後,你就可以像處理其他請求那樣處理當前請求了。首先,建立一個帶有<input type="file"/>
的表單,這樣使用者就可以通過這個表單上傳檔案了。為表單新增編碼屬性(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>
下一步是建立一個控制器來處理檔案上傳。這個控制器和之前那種正常的控制器很像,不過我們在方法引數上使用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();
// store the bytes somewhere
return "redirect:uploadSuccess";
}
return "redirect:uploadFailure";
}
}
注意@RequestParam
方法引數是怎樣對映到表單的 input 元素中的。在這個例子中,並沒有使用byte[]
做任何事,但是在實踐中,你可以把它儲存到資料庫中,也可以儲存到檔案系統上等,隨你咯。
上傳檔案之後不進行頁面跳轉
有時,想在上傳完頁面之後,頁面還保持在這裡,不去跳轉。這時,可以藉助<iframe/>
。把上面的表單改成下面那樣就行啦:
···
<form method="post" action="/form" enctype="multipart/form-data" target="myframe">
<input type="text" name="name"/>
<input type="file" name="file"/>
<input type="submit" value="上傳"/>
</form>
<iframe name="myframe"></iframe>
···