摘要:某段时间碰到了中转文件的需求,需要使用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. 【问题复盘】在Ubuntu 20.04下安装OFED驱动

    复盘:在Ubuntu 20.04下安装OFED驱动 起因 最近收到两台服务器,都搭载了ConnectX-5 EX网卡.由于供应商预装了Ubuntu 20.04操作系统,而我们的后端代码也是基于Ubun ...

  2. vscode 切换分支时报错:The following untracked working tree files would be overwritten .....

    执行命令:git clean -d -fx   表示删除 一些 没有 git add 的 文件: git clean 参数 -n 显示将要删除的文件和目录: -x -----删除忽略文件已经对git来 ...

  3. form表单调接口校验 比如后台验证用户名是否存在

    <FormItem {...formItemLayout} label={'显示名'}> {getFieldDecorator('displayName', { initialValue: ...

  4. off-line RL | CQL:魔改 Bellman error 更新,得到 Q 函数 lower-bound

    论文题目: Conservative Q-Learning for Offline Reinforcement Learning CQL 是师兄盛赞的一篇论文:"是 off-line RL ...

  5. 接雨水(4.4 leetcode每日打卡)

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水.   上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可 ...

  6. GitHub、Google等镜像加速地址收集

    摘要 本文用于收集GitHub.Google等镜像/加速地址. GitHub GitHub加速地址一览 fastgithub Https://www.fastgithub.com/(推荐) 站源 地址 ...

  7. [QOJ4815] Flower's Land

    简要题意:给出一个 \(n\) 个点的树,对某个点 \(i\) 求包含某一个点的大小为 \(k\) 的权值最大的连通块,一个连通块的权值是其所有点的权值之和. \(n\le 40000,k\le \m ...

  8. [ARC158D] Equation

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

  9. 终结篇:==和equals有什么区别?

    == 和 equals 有什么区别?这个问题本身不难,但是被问到的频率很高,且大部分人的回答都不够全面,让人听了有种"恨铁不成钢"的感觉,所以今天咱们就来好好聊聊这个问题. 1.典 ...

  10. 2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。

    2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值. 来自字节. 答案2023-12-16: 来自左程云. 灵捷3.5 大体步骤如下: 算 ...