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

    题目链接 题目分析 首先,看到题目中的左移右移之后再异或,我们自然可以想到在移动的过程中字符串的一段前缀和后缀不会改变,考虑通过这个性质逐位还原. 因为异或 0 不会改变原本的值,所以我们可以找到整个 ...

  2. GIT协作流程规范

    分支模型 集中式的分支模型 目前团队使用的模式属于老旧的集中式分支模型,简单的总结就是: 开发时: 团队的所有成员都在dev分支上开发(也支持少部分的特性分支feature-xxx). 测试时: 当功 ...

  3. JS深入之内存详解,数据结构,存储方式

    理解了本文,就知道深拷贝和浅拷贝的底层,了解赋值的底层原理. 可以结合另一篇文章一起食用:深拷贝与浅拷贝的区别,实现深拷贝的方法介绍. 以下是正文: 栈数据结构 栈的结构就是后进先出(LIFO),如果 ...

  4. node版本依赖报错那些事儿

    前言 昨天还能跑的的项目,今天就歇菜了 第一步 删除大法 依赖问题,那就把.lock/ node_modules 删除重新装 第二步 如果重装不好使,那就各种降低版本尝试 遇到这样的 有两种方式 1. ...

  5. Instagram 早期技术架构

    哈喽大家好,我是咸鱼 想必大家都听说过 Instagram ,它是全球最受欢迎的社交媒体平台之一,拥有数十亿的活跃用户 Instagram 诞生于 2010 年,上线一周就坐拥 10 万注册用户,一年 ...

  6. 两个对于电影片段的情绪研究(中国&国外)

    1.国内的研究(A new standardized emotional film database for Asian culture) 测试片使用了8种情绪类型,每部片子有4个维度的分数,分数是从 ...

  7. baby_web

    点开页面获得提示 根据提示,访问index.php,但是会自己跳转到1.php 这时候抓包修改才ok才能定位到index.php

  8. 文心一言 VS 讯飞星火 VS chatgpt (139)-- 算法导论11.4 3题

    三.用go语言,考虑一个采用均匀散列的开放寻址散列表.当装载因子为 3/4 和 7/8 时,试分别给出一次不成功查找和一次成功查找的探查期望数上界. 文心一言: 在开放寻址法中,当散列表的装载因子超过 ...

  9. SMTP操作使用详解并通过python进行smtp邮件发送示例

    转载请注明出处: 1.SMTP       SMTP 的全称是"Simple Mail Transfer Protocol",即简单邮件传输协议.它是一组用于从源地址到目的地址传输 ...

  10. 0x02.加密和编码

    识别算法编码类型 看密文位数 看密文特征(数字.字母.大小写.符号等) 看当前密文存在的地方(web.数据库.操作系统等) 密码存储加密 md5:16位和32位由0-9和a-f组成的字符串 ,该加密方 ...