MultipartFile的使用小結


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來說,創建相當簡便。

    1
    2
    3
    4
    5
    6
    7
    File 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的過程如下偽代碼所示:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    File file = new File("temp/fileItem/haha.jpg");
    if (!file.exists()) {
    file.mkdirs();
    }
    // 創建fileItem,具體方法參見第三節
    FileItem fileItem = new ...;
    // 將File內容寫入fileItem,使用org.apache.commons.io.IOUtils
    IOUtils.copy( new FileInputStream(file), fileItem.getOutputStream());
    // 創建multipartfile
    MultipartFile multipartFile = new CommonsMultipartFile(fileItem);

3. 如何創建FileItem?

FileItem接口只有一個實現類:DiskFileItem

  • 直接使用DiskFileItem創建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 創建fileItem
    FileItem fileItem = new DiskFileItem(
    "file", // 表單參數名
    ContentType.APPLICATION_OCTET_STREAM.toString(), // 文件類型
    false, // 是否為表單格式
    RandomKeyUtils.genRandomKey() + ".jpg", // 文件名
    10240, // 超過多少byte存在磁盤上
    new file("tmp/fileItem/") // 文件存儲位置
    );
  • 使用DiskFileItemFactory創建

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 小於5M文件都在內存中,否則存入硬盤
    final int tmpFileSize = 5242880;
    // 設置臨時文件大小以及臨時文件存儲路徑
    DiskFileItemFactory fileItemFactory = new DiskFileItemFactory(tmpFileSize, new file("tmp/fileItem/"));
    // 創建fileItem
    FileItem 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方法
    1. 普通Servlet中
      使用HttpServletRequest
      request.getSession().getServletContext()
    2. SpringMVC的Controller中
      使用SpringMVC提供的方法
      1
      2
      WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();
      ServletContext servletContext = webApplicationContext.getServletContext();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM