摘要:某段时间碰到了中转文件的需求,需要使用HttpClient中转一下文件,在实现这个需求的过程中就用得到了MultipartFile与File。

本文分享自华为云社区《MultipartFile与File的一些事》,作者: Copy工程师 。

前言

某段时间碰到了中转文件的需求,需要使用HttpClient中转一下文件,过程为:

在实现这个需求的过程中就用得到了MultipartFile与File,而且我对前一个也不是很熟悉。记录一下

什么是MultipartFile

MultipartFile是spring类型,代表HTML中form data方式上传的文件,包含二进制数据+文件名称。【来自百度知道】

MultipartFile 与 File 的 互相转换

1. File转MultipartFile

(1):使用org.springframework.mock.web.MockMultipartFile 需要导入spring-test.jar

  1. public static void main(String[] args) throws Exception {
  2. String filePath = "F:\\test.txt";
  3. File file = new File(filePath);
  4. FileInputStream fileInputStream = new FileInputStream(file);
  5. // MockMultipartFile(String name, @Nullable String originalFilename, @Nullable String contentType, InputStream contentStream)
  6. // 其中originalFilename,String contentType 旧名字,类型 可为空
  7. // ContentType.APPLICATION_OCTET_STREAM.toString() 需要使用HttpClient的包
  8. MultipartFile multipartFile = new MockMultipartFile("copy"+file.getName(),file.getName(),ContentType.APPLICATION_OCTET_STREAM.toString(),fileInputStream);
  9. System.out.println(multipartFile.getName()); // 输出copytest.txt
  10. }

(2):使用CommonsMultipartFile

  1. public static void main(String[] args) throws Exception {
  2. String filePath = "F:\\test.txt";
  3. File file = new File(filePath);
  4. // 需要导入commons-fileupload的包
  5. FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
  6. byte[] buffer = new byte[4096];
  7. int n;
  8. try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
  9. while ( (n = inputStream.read(buffer,0,4096)) != -1){
  10. os.write(buffer,0,n);
  11. }
  12. //也可以用IOUtils.copy(inputStream,os);
  13. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  14. System.out.println(multipartFile.getName());
  15. }catch (IOException e){
  16. e.printStackTrace();
  17. }
  18.  
  19. }

2. MultipartFile转File

(1):使用File转MultipartFile的逆过程

你在看这个代码的时候会觉得很熟悉,是的这个就是File转MultipartFile的逆转过程,这个方法会在根目录生成一个文件,需要删除该文件。

  1. public static void main(String[] args) throws Exception {
  2. int n;
  3. // 得到MultipartFile文件
  4. MultipartFile multipartFile = getFile();
  5. File f = null;
  6. // 输出文件的新name 就是指上传后的文件名称
  7. System.out.println("getName:"+multipartFile.getName());
  8. // 输出源文件名称 就是指上传前的文件名称
  9. System.out.println("Oriname:"+multipartFile.getOriginalFilename());
  10. // 创建文件
  11. f = new File(multipartFile.getOriginalFilename());
  12. try ( InputStream in = multipartFile.getInputStream(); OutputStream os = new FileOutputStream(f)){
  13. // 得到文件流。以文件流的方式输出到新文件
  14. // 可以使用byte[] ss = multipartFile.getBytes();代替while
  15. byte[] buffer = new byte[4096];
  16. while ((n = in.read(buffer,0,4096)) != -1){
  17. os.write(buffer,0,n);
  18. }
  19. // 读取文件第一行
  20. BufferedReader bufferedReader = new BufferedReader(new FileReader(f));
  21. System.out.println(bufferedReader.readLine());
  22. // 输出路径
  23. bufferedReader.close();
  24. }catch (IOException e){
  25. e.printStackTrace();
  26. }
  27. // 输出file的URL
  28. System.out.println(f.toURI().toURL().toString());
  29. // 输出文件的绝对路径
  30. System.out.println(f.getAbsolutePath());
  31. // 操作完上的文件 需要删除在根目录下生成的文件
  32. File file = new File(f.toURI());
  33. if (file.delete()){
  34. System.out.println("删除成功");
  35. }else {
  36. System.out.println("删除失败");
  37.  
  38. }
  39.  
  40. }
  41. /**
  42. *
  43. * @Description 返回MultipartFile文件
  44. * @return org.springframework.web.multipart.MultipartFile
  45. * @date 2019/1/5 11:08
  46. * @auther dell
  47. */
  48. public static MultipartFile getFile() throws IOException {
  49. String filePath = "F:\\test.txt";
  50. File file = new File(filePath);
  51. FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
  52. byte[] buffer = new byte[4096];
  53. int n;
  54. try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
  55. while ( (n = inputStream.read(buffer,0,4096)) != -1){
  56. os.write(buffer,0,n);
  57. }
  58. //也可以用IOUtils.copy(inputStream,os);
  59. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  60. System.out.println(multipartFile.getName());
  61. return multipartFile;
  62. }catch (IOException e){
  63. e.printStackTrace();
  64. }
  65. return null;
  66. }

(2):使用transferTo (本质上还是使用了流 只不过是封装了步骤)

会生成文件,最后不需要文件要删除

  1. public static void main(String[] args) throws Exception {
  2. String path = "F:\\demo\\";
  3. File file = new File(path,"demo.txt");
  4. // 得到MultipartFile文件
  5. MultipartFile multipartFile = getFile();
  6. /*byte[] ss = multipartFile.getBytes();
  7. OutputStream os = new FileOutputStream(file);
  8. os.write(ss);
  9. os.close();*/
  10. multipartFile.transferTo(file);
  11. // 读取文件第一行
  12. BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
  13. System.out.println(bufferedReader.readLine());
  14. // 输出绝对路径
  15. System.out.println(file.getAbsolutePath());
  16. bufferedReader.close();
  17. // 操作完上的文件 需要删除在根目录下生成的文件
  18. if (file.delete()){
  19. System.out.println("删除成功");
  20. }else {
  21. System.out.println("删除失败");
  22.  
  23. }
  24. }
  25. /**
  26. *
  27. * @Description 返回MultipartFile文件
  28. * @return org.springframework.web.multipart.MultipartFile
  29. * @date 2019/1/5 11:08
  30. * @auther dell
  31. */
  32. public static MultipartFile getFile() throws IOException {
  33. String filePath = "F:\\test.txt";
  34. File file = new File(filePath);
  35. FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
  36. byte[] buffer = new byte[4096];
  37. int n;
  38. try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
  39. while ( (n = inputStream.read(buffer,0,4096)) != -1){
  40. os.write(buffer,0,n);
  41. }
  42. //也可以用IOUtils.copy(inputStream,os);
  43. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  44. System.out.println(multipartFile.getName());
  45. return multipartFile;
  46. }catch (IOException e){
  47. e.printStackTrace();
  48. }
  49. return null;
  50. }

(3):使用FileUtils.copyInputStreamToFile()

也是会生成文件,到最后也是要删除文件

  1. public static void main(String[] args) throws Exception {
  2. String path = "F:\\demo\\";
  3. File file = new File(path,"demo.txt");
  4. // 得到MultipartFile文件
  5. MultipartFile multipartFile = getFile();
  6. // 把流输出到文件
  7. FileUtils.copyInputStreamToFile(multipartFile.getInputStream(),file);
  8. // 读取文件第一行
  9. BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
  10. System.out.println(bufferedReader.readLine());
  11. // 输出绝对路径
  12. System.out.println(file.getAbsolutePath());
  13. bufferedReader.close();
  14. // 操作完上的文件 需要删除在根目录下生成的文件
  15. if (file.delete()){
  16. System.out.println("删除成功");
  17. }else {
  18. System.out.println("删除失败");
  19.  
  20. }
  21. }
  22. /**
  23. *
  24. * @Description 返回MultipartFile文件
  25. * @return org.springframework.web.multipart.MultipartFile
  26. * @date 2019/1/5 11:08
  27. * @auther dell
  28. */
  29. public static MultipartFile getFile() throws IOException {
  30. String filePath = "F:\\test.txt";
  31. File file = new File(filePath);
  32. FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
  33. byte[] buffer = new byte[4096];
  34. int n;
  35. try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
  36. while ( (n = inputStream.read(buffer,0,4096)) != -1){
  37. os.write(buffer,0,n);
  38. }
  39. //也可以用IOUtils.copy(inputStream,os);
  40. MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
  41. System.out.println(multipartFile.getName());
  42. return multipartFile;
  43. }catch (IOException e){
  44. e.printStackTrace();
  45. }
  46. return null;
  47. }

4:强转类型

  1. CommonsMultipartFile commonsmultipartfile = (CommonsMultipartFile) multipartFile;
  2. DiskFileItem diskFileItem = (DiskFileItem) commonsmultipartfile.getFileItem();
  3. File file = diskFileItem.getStoreLocation();

这种强转你获得的file只是一个空壳

你能获取的也只有这个F:\upload_edfce39f_2894_4b66_b865_d5fb8636bdf3_00000000.tmp 网上有说会在根目录生成临时文件的,从tmp也可以看出来是个临时文件,但是我试了好几次啥都没找到。。。。直接获取这个file读取内容也是会报文件找不到的 这是必然的 当然也有在spring配置文件配置CommonsMultipartResolver的 这就感觉很麻烦了。。。。

但是我们可以看一下diskFileItem 看下图 是不是很熟悉了,从diskFileItem可以获取文件流,其实你看了源码你就知道获取文件流都是从这里获取的。剩下的就好办了 我就不赘述了/。

在使用临时文件的时候可以使用缓冲区创建临时文件

  1. // createTempFile(String prefix, String suffix)
  2. // prefix 文件名 suffix 文件格式
  3. // 默认是tmp格式 C:\Users\dell\AppData\Local\Temp\tmp8784723057512789016.tmp
  4. File file =File.createTempFile("tmp", null);
  5. // txt格式 C:\Users\dell\AppData\Local\Temp\tmp2888293586594052933.txt
  6. File file =File.createTempFile("tmp", ".txt");

HttpClient构建上传文件参数并实现中转文件

这里不自己给例子了,参考了其他博客的代码

  1. // 获取文件名称
  2. String fileName = file.getOriginalFilename();
  3. HttpPost httpPost = new HttpPost(url);
  4. // 创建文件上传实体
  5. MultipartEntityBuilder builder = MultipartEntityBuilder.create();
  6. builder.addBinaryBody("file", file.getInputStream(), ContentType.MULTIPART_FORM_DATA, fileName);
  7. builder.addTextBody("filename", fileName);
  8. HttpEntity entity = builder.build();
  9. httpPost.setEntity(entity);
  10. HttpResponse response = httpClient.execute(httpPost);// 执行提交

执行提交之后你会发现你上传的文件名会出现中文乱码

我使用的解决办法是:

  1. //设置模式为RFC6532
  2. builder.setMode(HttpMultipartMode.RFC6532);

点击关注,第一时间了解华为云新鲜技术~

MultipartFile与File的一些事的更多相关文章

  1. [转]spring MultipartFile 转 File

    原文地址:https://www.jianshu.com/p/6cf99d39e170 File.createTempFile(String prefix, String suffix); 创建一个临 ...

  2. Springmvc 上传文件MultipartFile 转File

    转自:http://blog.csdn.net/boneix/article/details/51303207 业务场景:ssm框架 上传文件到应用服务器过程中要传到专有的文件服务器并返回url进行其 ...

  3. MultipartFile 转换为File

    选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 . MultipartFile multipartFile; File fil ...

  4. Multipartfile与File类型相互转换

    特殊情况下需要做转换 1.M转F File file = new File(path); FileUtils.copyInputStreamToFile(multipartFile.getInputS ...

  5. SpringMVC 上传文件 MultipartFile 转为 File

    在使用 SpringMVC 上传文件时,接收到的文件格式为 MultipartFile,但是在很多场景下使用都需要File格式的文件,记录下以便日后使用. 以下mFile为MultipartFile文 ...

  6. spring MVC 的MultipartFile转File??

    MultipartFile file = xxx;         CommonsMultipartFile cf= (CommonsMultipartFile)file;         DiskF ...

  7. spring MVC 的MultipartFile转File读取

    转自:http://www.cnblogs.com/hahaxiaoyu/p/5102900.html 第一种方法:   MultipartFile file = xxx;         Commo ...

  8. 关于Java数据转存的中MultipartFile转File的问题(转)

    转自http://www.cnblogs.com/zuoxiaoxia/p/6116942.html 错误背景:由于文件储存在第三方的服务器上,所有需要讲将接收到MultipartFile文件 转换为 ...

  9. Required MultipartFile parameter 'file' is not present error

    <input type=“file”>  中的name 与id 属性 与  addbanner(@RequestParam("file") MultipartFile ...

  10. springmvc 中将MultipartFile转为file,springboot 注入CommonsMultipartResolver

    第一种方法: MultipartFile file = xxx; CommonsMultipartFile cf= (CommonsMultipartFile)file; DiskFileItem f ...

随机推荐

  1. 2023云栖大会议程&体验攻略

    2023云栖大会倒计时1天 将围绕"计算,为了无法计算的价值" 为大家带来一场有用.有趣科技盛宴 City Walk 不如云栖Walk 今日,送上一份参会指南 给所有参会者& ...

  2. html-7(JavaScript-1)

    放在函数里面 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <ti ...

  3. Welcome to YARP - 7.目标健康检查

    目录 Welcome to YARP - 1.认识YARP并搭建反向代理服务 Welcome to YARP - 2.配置功能 2.1 - 配置文件(Configuration Files) 2.2 ...

  4. 关于微信小程序中如何实现数据可视化-echarts动态渲染

    移动端设备中,难免会涉及到数据的可视化展示.数据统计等等,本篇主要讲解原生微信小程序中嵌入echarts并进行动态渲染,实现数据可视化功能. 基础使用 首先在GitHub上下载echarts包 地址: ...

  5. 4. Shell 循环语句

    重点: 条件测试. read. Shell 环境配置. case. for. find. xargs. gzip,bzip2,xz. tar. sed. 1)循环 1.1)循环执行介绍 将某代码段重复 ...

  6. 快速下载vscode、git

    在官网下载vscode太慢,解决方式: http://vscode.cdn.azure.cn/stable/ea3859d4ba2f3e577a159bc91e3074c5d85c0523/VSCod ...

  7. [ARC158D] Equation

    Problem Statement You are given a positive integer $n$, and a prime number $p$ at least $5$. Find a ...

  8. PyTorch 中自定义数据集的读取方法

    显然我们在学习深度学习时,不能只局限于通过使用官方提供的MNSIT.CIFAR-10.CIFAR-100这样的数据集,很多时候我们还是需要根据自己遇到的实际问题自己去搜集数据,然后制作数据集(收集数据 ...

  9. 【UniApp】-uni-app-传递数据

    前言 好,经过上个章节的介绍完毕之后,了解了一下 uni-app-路由 那么了解完了uni-app-路由之后,这篇文章来给大家介绍一下 uni-app-路由传递数据 路由传参怎么传,是不是可以从 A ...

  10. Java8函数式编程应用

    我们经常提到,Java8是革命性的一个版本,原因就是正式引入了函数式编程,那Java的函数式编程在实际应用中到底有什么用呢?结合实际的应用,我整理出了函数式在Java的几个经典用途. 缓求值 惰性求值 ...