摘要:某段时间碰到了中转文件的需求,需要使用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

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

(2):使用CommonsMultipartFile

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

2. MultipartFile转File

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

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

 public static void main(String[] args) throws Exception {
int n;
// 得到MultipartFile文件
MultipartFile multipartFile = getFile();
File f = null;
// 输出文件的新name 就是指上传后的文件名称
System.out.println("getName:"+multipartFile.getName());
// 输出源文件名称 就是指上传前的文件名称
System.out.println("Oriname:"+multipartFile.getOriginalFilename());
// 创建文件
f = new File(multipartFile.getOriginalFilename());
try ( InputStream in = multipartFile.getInputStream(); OutputStream os = new FileOutputStream(f)){
// 得到文件流。以文件流的方式输出到新文件
// 可以使用byte[] ss = multipartFile.getBytes();代替while
byte[] buffer = new byte[4096];
while ((n = in.read(buffer,0,4096)) != -1){
os.write(buffer,0,n);
}
// 读取文件第一行
BufferedReader bufferedReader = new BufferedReader(new FileReader(f));
System.out.println(bufferedReader.readLine());
// 输出路径
bufferedReader.close();
}catch (IOException e){
e.printStackTrace();
}
// 输出file的URL
System.out.println(f.toURI().toURL().toString());
// 输出文件的绝对路径
System.out.println(f.getAbsolutePath());
// 操作完上的文件 需要删除在根目录下生成的文件
File file = new File(f.toURI());
if (file.delete()){
System.out.println("删除成功");
}else {
System.out.println("删除失败"); } }
/**
*
* @Description 返回MultipartFile文件
* @return org.springframework.web.multipart.MultipartFile
* @date 2019/1/5 11:08
* @auther dell
*/
public static MultipartFile getFile() throws IOException {
String filePath = "F:\\test.txt";
File file = new File(filePath);
FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
byte[] buffer = new byte[4096];
int n;
try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
while ( (n = inputStream.read(buffer,0,4096)) != -1){
os.write(buffer,0,n);
}
//也可以用IOUtils.copy(inputStream,os);
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
System.out.println(multipartFile.getName());
return multipartFile;
}catch (IOException e){
e.printStackTrace();
}
return null;
}

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

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

public static void main(String[] args) throws Exception {
String path = "F:\\demo\\";
File file = new File(path,"demo.txt");
// 得到MultipartFile文件
MultipartFile multipartFile = getFile();
/*byte[] ss = multipartFile.getBytes();
OutputStream os = new FileOutputStream(file);
os.write(ss);
os.close();*/
multipartFile.transferTo(file);
// 读取文件第一行
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
System.out.println(bufferedReader.readLine());
// 输出绝对路径
System.out.println(file.getAbsolutePath());
bufferedReader.close();
// 操作完上的文件 需要删除在根目录下生成的文件
if (file.delete()){
System.out.println("删除成功");
}else {
System.out.println("删除失败"); }
}
/**
*
* @Description 返回MultipartFile文件
* @return org.springframework.web.multipart.MultipartFile
* @date 2019/1/5 11:08
* @auther dell
*/
public static MultipartFile getFile() throws IOException {
String filePath = "F:\\test.txt";
File file = new File(filePath);
FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
byte[] buffer = new byte[4096];
int n;
try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
while ( (n = inputStream.read(buffer,0,4096)) != -1){
os.write(buffer,0,n);
}
//也可以用IOUtils.copy(inputStream,os);
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
System.out.println(multipartFile.getName());
return multipartFile;
}catch (IOException e){
e.printStackTrace();
}
return null;
}

(3):使用FileUtils.copyInputStreamToFile()

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

public static void main(String[] args) throws Exception {
String path = "F:\\demo\\";
File file = new File(path,"demo.txt");
// 得到MultipartFile文件
MultipartFile multipartFile = getFile();
// 把流输出到文件
FileUtils.copyInputStreamToFile(multipartFile.getInputStream(),file);
// 读取文件第一行
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
System.out.println(bufferedReader.readLine());
// 输出绝对路径
System.out.println(file.getAbsolutePath());
bufferedReader.close();
// 操作完上的文件 需要删除在根目录下生成的文件
if (file.delete()){
System.out.println("删除成功");
}else {
System.out.println("删除失败"); }
}
/**
*
* @Description 返回MultipartFile文件
* @return org.springframework.web.multipart.MultipartFile
* @date 2019/1/5 11:08
* @auther dell
*/
public static MultipartFile getFile() throws IOException {
String filePath = "F:\\test.txt";
File file = new File(filePath);
FileItem fileItem = new DiskFileItem("copyfile.txt", Files.probeContentType(file.toPath()),false,file.getName(),(int)file.length(),file.getParentFile());
byte[] buffer = new byte[4096];
int n;
try (InputStream inputStream = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()){
while ( (n = inputStream.read(buffer,0,4096)) != -1){
os.write(buffer,0,n);
}
//也可以用IOUtils.copy(inputStream,os);
MultipartFile multipartFile = new CommonsMultipartFile(fileItem);
System.out.println(multipartFile.getName());
return multipartFile;
}catch (IOException e){
e.printStackTrace();
}
return null;
}

4:强转类型

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

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

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

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

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

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

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

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

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

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

我使用的解决办法是:

 //设置模式为RFC6532
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. 基于Electron27+Vite4+React18搭建桌面端项目|electron多开窗口实践

    前段时间有分享一篇electron25+vite4搭建跨桌面端vue3应用实践.今天带来最新捣鼓的electron27+react18创建跨端程序.electron多开窗体(模拟QQ登录窗口切换主窗口 ...

  2. Chromium Canvas工作流

    blink 中实现了2种 canvas,分别是 blink::HTMLCanvasElement 和 blink::OffscreenCanvas ,前者对应 html/dom 中的 canvas,后 ...

  3. 多巴胺所表达的prediction error信号

    Dopamine reward prediction-error signalling: a two-component response (Wolfram Schultz; NATURE REVIE ...

  4. 【源码解读(二)】EFCORE源码解读之查询都做了什么以及如何自定义批量插入

    引言 书接上回,[源码解读(一)]EFCORE源码解读之创建DBContext查询拦截,在上一篇文章中,主要讲了DBContext的构造函数,以及如何缓存查询方法提升查询性能,还有最重要的拦截查询,托 ...

  5. easy_enc

    寻找main函数,步过好像没有main函数,这时候想要F5就只能找到对的函数了 F5以后发现进行的操作有很多,这里发现有几个都没用的 后面发现主要是对V5有操作,所以直接看有关于V5的操作函数 经过上 ...

  6. DiscuzQ官方最新v3.0.220211源码编译搭建教程和官方部署教程,适合二开(已本地编译通过,无任何错误)

    经过长达半个月的研究! 完成这篇DiscuzQ官方最新版本v3.0.220211的源码编译和官方部署教程.适合喜欢二次开发的小伙伴们,已经通过本地编译测试,保证没有任何错误. 具体教程在我搭建的dzq ...

  7. JAVA中的函数接口,你都用过吗

    公众号「架构成长指南」,专注于生产实践.云原生.分布式系统.大数据技术分享. 在这篇文章中,我们将通过示例来学习 Java 函数式接口. 函数式接口的特点 只包含一个抽象方法的接口称为函数式接口. 它 ...

  8. JSX、TSX 整体理解

    可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么? JS JavaScript 是互联网上最流行的脚本语言,这门语言可用于 HTML 和 web, ...

  9. 提升效率,打通万里牛ERP与下游用友U8财务软件的无缝对接

    一.对接流程 1.1 销售/售后流程 在万里牛订单出库后,通过轻易云数据集成平台将数据推送至用友U8销售订单和销售出库单,这些单据可以进行关联操作. 当万里牛售后单完成退货入库后,通过数据集成平台将数 ...

  10. hive报错Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask[已解决]

    我的报错信息 Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.mr.MapRedTask 解决1(可行):不走ya ...