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中使用HttpServletRequest
request.getSession().getServletContext()
- SpringMVC的Controller中使用SpringMVC提供的方法 12WebApplicationContext webApplicationContext = ContextLoader.getCurrentWebApplicationContext();ServletContext servletContext = webApplicationContext.getServletContext();
- 普通Servlet中使用HttpServletRequest