Multipartfile轉File?File轉MultipartFile?可千萬別轉暈了。
題圖:from Google
1. MultipartFile類型轉File類型
想要將MultipartFile類型轉為File類型可以使用MultipartFile提供的方法:void MultipartFile.transferTo(File dest) throws IOException, IllegalStateException
1
2
3
4
5
6
|
File destFile =
new File("tmp/source/destFile");
if (!fileSourcePath.exists()) {
fileSourcePath.mkdirs();
}
// 將MultipartFile存到臨時文件中
mulFileSource.transferTo(destFile);
|
2. File類型轉Multipartfile
MultipartFile接口有兩個常用實現類,MockMultipartFile和CommonsMultipartFile。
-
使用MockMultipartFile
看名字就知道MockMultipartFile主要用於測試用途,但是相對CommonsMultipartFile來說,創建相當簡便。1234567File file = new File("/Users/coderec/Desktop/haha.jpg");MultipartFile mulFile = new MockMultipartFile("haha.jpg", //文件名"haha.jpg", //originalName 相當於上傳文件在客戶機上的文件名ContentType.APPLICATION_OCTET_STREAM.toString(), //文件類型new FileInputStream(file) //文件流); -
使用CommonsMultipartFile
與MockMultipartFile相比,CommonsMultipartFile僅僅有一個構造方法:CommonsMultipartFile(FileItem fileItem)
因此,若要使用CommonsMultipartFile來創建MultipartFile就一定要使用FileItem。通過FileItem將File轉化為MultipartFile的過程如下偽代碼所示:12345678910File file = new File("temp/fileItem/haha.jpg");if (!file.exists()) {file.mkdirs();}// 創建fileItem,具體方法參見第三節FileItem fileItem = new ...;// 將File內容寫入fileItem,使用org.apache.commons.io.IOUtilsIOUtils.copy( new FileInputStream(file), fileItem.getOutputStream());// 創建multipartfileMultipartFile multipartFile = new CommonsMultipartFile(fileItem);
3. 如何創建FileItem?
FileItem接口只有一個實現類:DiskFileItem
-
直接使用DiskFileItem創建
123456789// 創建fileItemFileItem fileItem = new DiskFileItem("file", // 表單參數名ContentType.APPLICATION_OCTET_STREAM.toString(), // 文件類型false, // 是否為表單格式RandomKeyUtils.genRandomKey() + ".jpg", // 文件名10240, // 超過多少byte存在磁盤上new file("tmp/fileItem/") // 文件存儲位置); -
使用DiskFileItemFactory創建
1234567891011// 小於5M文件都在內存中,否則存入硬盤final int tmpFileSize = 5242880;// 設置臨時文件大小以及臨時文件存儲路徑DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(tmpFileSize, new file("tmp/fileItem/"));// 創建fileItemFileItem fileItem = fileItemFactory.createItem("file", // 表單參數名ContentType.APPLICATION_OCTET_STREAM.toString(), // 文件類型false, // 是否為表單格式RandomKeyUtils.genRandomKey() + ".jpg" // 文件名);
4. DiskFileItem產生的臨時文件處理
- 使用內存存儲,不寫入硬盤
在創建FileItem時,可以設定一個較大的文件大小,使文件不被寫入硬盤,就不會產生臨時文件的問題。不過這不是一個正確的解決問題的方式。而且,也會受到內存大小限制。 - 使用FileCleaningTracker
在使用DiskFileItemFactory時,應該會發現其有一個void setFileCleaningTracker(FileCleaningTracker pTracker)
方法,此方法就是為臨時文件設置監聽線程,一旦發現臨時文件被垃圾回收,就會清除臨時文件。
我們可以通過FileCleanerCleanup監聽器以及ServletContext獲得監聽線程FileCleaningTracker。
為FileItem設置監聽的過程如下:
1
2
3
4
5
|
FileCleaningTracker fileCleaningTracker
= FileCleanerCleanup.getFileCleaningTracker(servletContext);
DiskFileItemFactory factory
=
new DiskFileItemFactory(10240, File("tmp/fileItem/");
factory.setFileCleaningTracker(fileCleaningTracker);
|
在不需要監聽線程FileCleaningTracker時,應該將其停止。可以在web.xml中進行如下配置:
1
2
3
4
5
6
7
8
9
|
<web-app>
...
<listener>
<listener-class>
org.apache.commons.fileupload.servlet.FileCleanerCleanup
</listener-class>
</listener>
...
</web-app>
|
- 獲取ServletContext方法
- 普通Servlet中
使用HttpServletRequestrequest.getSession().getServletContext()
- SpringMVC的Controller中
使用SpringMVC提供的方法12WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();ServletContext servletContext = webApplicationContext.getServletContext();