byte[]转MultipartFile、byte[]转File一次看个够

目录

需求背景

当你需要将byte[]MultipartFileFile实现互转时,无外乎以下场景:

  1. 保存第三方接口返回二进制流
  2. 前/后端文件流上传
  3. 微服务间调用
  4. 文件格式转换

正如你所需要的,通过搜索引擎筛选到我的本篇文章是因为你在开发中需要将byte[]转为MultipartFileFile格式的文件,以上需求在业务开发中是用户、客户、产品经理所喜闻乐见的,类似的文章在各大博客平台同样多如牛毛,也许你看了许多其他博主写的文章,按他们的代码按部就班去做但并没达到你需要的效果,是的,我在开发过程中也遇到了这样的痛点,因此有了这篇文章,写本文的目的意在为自己积累知识点,另外也帮助他人少走弯路。

希望我的文章能够帮您快速、高效解决您的问题,这是我莫大的荣幸。

“赠人玫瑰,手有余香” --谚语

byte[]转MultipartFile

错误示例-MockMultipartFile

首先来看一下摘自Spring官网对MockMultipartFile的一段描述:

public class MockMultipartFile extends Object implements MultipartFile

Mock implementation of the MultipartFile interface.

Useful in conjunction with a MockMultipartHttpServletRequest for testing application controllers that access multipart uploads.

虽然MockMultipartFile实现了MultipartFile接口,重点在于后一句对其作用的描述:用于测试访问分段上传, 所以这个类在正式环境是无法使用的,在我看来使用MockMultipartFile来实现byte[]MockMultipartFile的博客都是误人子弟,因为你的代码不仅仅是运行在测试类中,而都是要发布在生产环境的。

maven坐标:

<!-- https://mvnrepository.com/artifact/org.springframework/spring-mock -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-mock</artifactId>
  <version>2.0.8</version>
  <scope>test</scope>
</dependency>
byte[] testFile = new byte[1024];
InputStream inputStream = new ByteArrayInputStream(testFile);
MultipartFile file = new MockMultipartFile(ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);

CommonsMultipartFile介绍

CommonsMultipartFileSpring 框架3.1版本后引入,用于与Apache Commons FileUpload 库集成的适配器。它实现了 SpringMultipartFile 接口,允许你将Apache Commons FileUploadFileItem 对象作为 SpringMultipartFile 来使用。

CommonsMultipartFile实现

以maven的方式如何引入CommonsMultipartFile

<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.4</version>
</dependency>

实现代码:

private static MultipartFile convertByteToMultipartFile(byte[] imageBytes,String fileName) {
    if (Objects.isNull(imageBytes)) {
        log.error("获取微信小程序码图片信息失败,接口返回为空");
        throw new CustomException("由于输入byte数组为空,导致转换为MultipartFile失败");
    }
    String contentType = "image/jpeg";

    FileItem item;
    try {
        FileItemFactory factory = new DiskFileItemFactory();
        item = factory.createItem("file", contentType, false, fileName);

        try (ByteArrayOutputStream bos = new ByteArrayOutputStream(imageBytes.length);
             OutputStream os = item.getOutputStream()) {

            bos.write(imageBytes);
            os.write(bos.toByteArray());
        }
        return new CommonsMultipartFile(item);
    } catch (IOException e) {
        log.error("转换微信小程序码图片信息为MultipartFile时发生错误", e);
        throw new CustomException("转换过程中发生错误", e);
    }
}

byte[]转File

byte[]File的实现方式更多一些,很多第三方高质量的轮子提供了均对应的方法,无需自行实现,调用API即可,下文以HuTool``与Apache Commons lang3举例。

前置条件-获取文件byte[]

以下代码从本地读取文件并转为byte[]用于模拟业务逻辑。

    /**
     * 将文件内容读取到字节数组中。
     *
     * @param filePath 文件路径
     * @return 字节数组,如果文件不存在或读取过程中发生错误,则返回null
     */
    public static byte[] getFileBytes(String filePath) {
        File file = new File(filePath);
        // 检查文件是否存在
        if (!file.exists()) {
            System.out.println("文件不存在");
            return null;
        }

        try (// 使用try-with-resources语句自动管理资源
             FileChannel fileChannel = new RandomAccessFile(file, "r").getChannel()) {
            // 分配一个ByteBuffer,大小为文件的大小
            ByteBuffer byteBuffer = ByteBuffer.allocate((int) fileChannel.size());
            // 从文件通道读取数据到ByteBuffer
            fileChannel.read(byteBuffer);
            // 反转ByteBuffer的limit和position,使得可以通过array()方法获取数据
            byteBuffer.flip();
            // 返回包含文件数据的字节数组
            return byteBuffer.array();
        } catch (IOException e) {
            // 如果发生IO异常,记录错误日志并返回null
            e.printStackTrace(); // 这里假设e.printStackTrace()是日志记录的一种形式
            return null;
        }
    }
}

以Hutool的方式

引入Hutool

以maven坐标的方式:

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.26</version>
</dependency>

以Gradle的方式:

implementation 'cn.hutool:hutool-all:5.8.26'

具体请参考官方文档:

Hutool快速入门

byte[] data = getFileBytes("src/main/resources/banner.txt");
// 指定要创建的文件路径
String filePath = "/path/to/your/output/file";
// 使用HuTool将byte数组写入到文件
File file = FileUtil.writeBytes(data, filePath);

以Apache Commons IO的方式

引入Apache Commons IO

以maven坐标的形式:

<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.16.1</version>
</dependency>

以Gradle的形式:

implementation 'commons-io:commons-io:2.16.1'

代码实现:

public static void main(String[] args) {
  try {
    //业务逻辑中获取到的byte[]
    byte[] fileBytes = getFileBytes("src/main/resources/banner.txt");
    //目标文件
    String outputFilePath = "src/main/resources/banner22.txt";
    File outputFile = writeBytesToFile(outputFilePath, fileBytes);
    log.error("文件写入成功,输出文件路径: {}", outputFile.getAbsolutePath());
  } catch (IOException e) {
    log.error("转换错误", e);
  }
}


public static File writeBytesToFile(String filePath, byte[] fileBytes) throws IOException {
  File outputFile = new File(filePath);
  FileUtils.writeByteArrayToFile(outputFile, fileBytes);
  // 返回File对象
  return outputFile;
}

MultipartFile与File互转

字节数组可以转换为File,同样也可以转换为MultipartFile,那么MultipartFileFile之间的互转可以利用byte[]作为中间桥梁。

MultipartFile转File

MultipartFile接口提供了getInputStream()方法,你可以使用这个方法来读取文件内容,并将它们写入到一个新的File对象中。

public class MultipartFileToFileConverter {

    public static File convert(MultipartFile multipartFile, String filePath) throws IOException {
        // 检查MultipartFile是否为空
        if (multipartFile == null || multipartFile.isEmpty()) {
            throw new IOException("文件为空");
        }

        // 创建File对象
        File file = new File(filePath);

        // 使用try-with-resources语句自动关闭资源
        try (InputStream inputStream = multipartFile.getInputStream();
             FileOutputStream outputStream = new FileOutputStream(file)) {

            // 将输入流中的数据写入到输出流(即文件)中
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }

        // 返回创建的File对象
        return file;
    }
}

File转MultipartFile

FileMultipartFile同样需要依赖于CommonsMultipartFile

public class FileToMultipartFileConverter {

    public static MultipartFile convert(File file) throws IOException, FileUploadException {
        // 创建FileItemFactory实例
        FileItemFactory factory = new DiskFileItemFactory();

        // 创建一个FileItem来包装File对象
        org.apache.commons.fileupload.FileItem fileItem = factory.createItem(
                "file", // 表单字段名,可以自定义
                "application/octet-stream", // 内容类型
                true, // 是否使用临时文件存储上传的数据
                file.getName() // 文件名
        );

        // 将File对象的内容写入到FileItem中
        fileItem.write(new File(fileItem.getName()));

        // 使用CommonsMultipartFile来包装FileItem
        return new DiskFileItem(fileItem).getStoreLocation();
    }
}

星空不问赶路人,岁月不负有心人。

wallhaven-p9z9qm (1).jpg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/727974.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

10万人寻梦玩具好莱坞 ,一人逆袭年销1.8个亿

文丨王一粟 周效敬 奥特曼、四驱赛车、毛绒玩具......如果有一个地方能实现玩具自由&#xff0c;那一定是广东澄海。 澄海是中国乃至世界的玩具之都&#xff0c;给亿万的孩子甚至长大了的孩子带来无数快乐&#xff0c;堪称玩具好莱坞。 无数的年轻人怀揣着实现财富自由的梦想…

【机器学习】机器的登神长阶——AIGC

目录 什么是AIGC 普通用户接触AIGC网站推荐 通义千问 白马 普通用户如何用好AIGC 关键提示词的作用 AIGC的影响 就业市场&#xff1a; 教育领域&#xff1a; 创意产业&#xff1a; 经济活动&#xff1a; 社交媒体与信息传播&#xff1a; AIGC面临的挑战 什么是AIGC…

Linux--视频推流及问题

方案一&#xff1a; mjpg-streamer,它运行在ARM板上 在手机上使用浏览器直接观看视频 方案二&#xff1a; 推流端&#xff08;Fmpeg&#xff09;--rtmp-->Nginx&#xff08;流媒体服务器&#xff09;--rtmp/httpflv/hls-->浏览器、播放器 此篇文章记录方案二的具体细…

Vue中使用ElementUI组件Form组件的校验validate

先准备一些el-form元素 这里面el-form中:model(v-bind:model)是单项绑定的&#xff0c;如果你写成了v-model""可能会出现校验没有效果的情况。 这是校验过后的结果了 现在开始使用下吧&#xff01; 1.在el-form中绑定一个ref&#xff0c;名字自拟,后续触发检验结果…

Java实现俄罗斯方块——文本域组件

技术实现&#xff1a; 1.初始化游戏窗口&#xff1b; 2.初始化游戏界面&#xff1b; 3.初始化游戏的说明面板&#xff1b; 4.随机生成下落方块&#xff1b; 5.绘制方块&#xff1b; 6.清除方块&#xff1b; 7.清楚某一行方块&#xff0c;上方方块掉落&#xff1b; 8.刷新…

【C语言】指向指针的指针使用场景

前言 C 语言中&#xff0c;比较难理解的就是指针&#xff0c;完全搞懂了指针&#xff0c;那么C语言算是入了门。 指针中比较难理解的概念&#xff1a; 指针的指针。 指针的指针&#xff0c;刚开始看到这个概念&#xff0c;感觉头疼。但是我们在程序里面应用一次就能搞懂。 本文…

web中间件漏洞-jboss部署war包

web中间件漏洞-jboss部署war包 攻击机服务器准备好的ma.war

【ARMv8/v9 GIC 系列 4.1 -- GIC CPU Interface 访问支持情况】

文章目录 GIC CPU Interface 访问支持Bit[27:24]: GIC CPU接口汇编代码实现访问小结 GIC CPU Interface 访问支持 在ARMv8架构中&#xff0c;ID_AA64PFR0_EL1是一个系统寄存器&#xff0c;提供了有关处理器功能的详绀信息。这个寄存器的位[27:24]专门用于描述GIC&#xff08;通…

使用PlugLink实现自动化运营:提升效率的秘密武器(附源码)

使用PlugLink实现自动化运营&#xff1a;提升效率的秘密武器 作为一款开源的自动化工具&#xff0c;PlugLink可以帮助个人和小微企业实现运营自动化&#xff0c;极大地提升工作效率&#xff0c;降低运营成本。 一、PlugLink简介 PlugLink是一个基于Python的开源自动化工具框…

【数据库系统概论复习】关系数据库与关系代数笔记

文章目录 基本概念数据库基本概念关系数据结构完整性约束 关系代数关系代数练习课堂练习 语法树 基本概念 数据库基本概念 DB 数据库&#xff0c; 为了存用户的各种数据&#xff0c;我们要建很多关系&#xff08;二维表&#xff09;&#xff0c;所以把相关的关系&#xff08;二…

SpringBoot复习

第一章 SpringBoot开发入门 1.Springboot的优点。 ① 可快速构建独立的Spring应用。 ② 直接嵌入Tomcat、Jetty和Undertow服务器&#xff08;无须部署WAR文件&#xff09; ③ 通过依赖启动器简化构建配置 ④ 自动化配置Spring和第三方库 ⑤ 提供生产就绪功能 ⑥ 极少的代码生成…

自由度与反证法

在 一道全等三角形几何证明题 的最后我使用反证法获得了解法三&#xff0c;但只是稍微提到了自由度&#xff0c;本文详细说一下&#xff0c;然后下一篇文章给出我的一个求最小生成树的新方法&#xff0c;同样基于自由度和反证法。 再次给出那道几何题&#xff0c;并给出一些话…

JAVA系列---Servlet

Servlet 处理 HTTP 请求的流程 一般情况下&#xff0c;浏览器&#xff08;客户端&#xff09;通过 HTTP 协议来访问服务器的资源&#xff0c;Servlet 主要用来处理 HTTP 请求。核心对象有三个 Servlet&#xff1a;提供service()方法处理请求ServletRequest&#xff1a;请求信…

SQL Developer功能又进化了!这波改造,可靠

作者&#xff1a;IT邦德 中国DBA联盟(ACDU)成员&#xff0c;10余年DBA工作经验&#xff0c; Oracle、PostgreSQL ACE CSDN博客专家及B站知名UP主&#xff0c;全网粉丝10万 擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复&#xff0c; 安装迁移&#xff0c;性能优化、故障…

Vue-观察器(watch)的定义方式引发组件初始值没有渲染成功问题(已解决)

问题描述&#xff1a;在测试环境发现一个问题&#xff0c;打开一张表单的时候&#xff0c;所有字段都成功赋上了值&#xff0c;唯独一个人员组件的值&#xff08;出差人员&#xff09;没有带出&#xff0c;而接口返回的数据是正常的&#xff0c;也就是说不是后端接口的问题&…

手把手教你如何部署自己的One Tool助手

手把手教你如何部署自己的One Tool助手 前言安装教程效果图在这里插入图片描述 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/0fc5cb0f451e4c50b55ec850a5517b0c.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/56331f878b9545d5bff6f938c4b317…

WPF中的隧道路由和冒泡路由事件

文章目录 简介:一、事件最基本的用法二、理解路由事件简介: WPF中使用路由事件升级了传统应用开发中的事件,在WPF中使用路由事件能更好的处理事件相关的逻辑,我们从这篇开始整理事件的用法和什么是直接路由,什么是冒泡路由,以及什么是隧道路由。 一、事件最基本的用法 …

Zookeeper基础教程

Zookeeper基础教程 资料来源&#xff1a;Zookeeper Tutorial (tutorialspoint.com) zookeeper就是Hadoop生态动物园的管理员 1. Zookeeper-概述 ZooKeeper是一种分布式协调服务&#xff0c;用于管理大型主机集群(large set of hosts)。在分布式环境中协调和管理服务是一个复…

第三期【Demo教程】教你使用SeaTunnel把数据从MySQL导到Hive

随着数据技术的快速发展&#xff0c;了解并掌握各种工具和技术变得尤为重要。为此&#xff0c;我们准备在Apache SeaTunnel社区发起如何使用连接器的Demo演示计划&#xff0c;邀请所有热爱数据同步技术的同学分享他们的知识和实操经验! 我们第三期主题是&#xff1a;如何使用Se…

Cesium源码解析六(3dtiles属性获取、建筑物距离计算、建筑物着色及其原理分析)

快速导航 Cesium源码解析一&#xff08;搭建开发环境&#xff09; Cesium源码解析二&#xff08;terrain文件的加载、解析与渲染全过程梳理&#xff09; Cesium源码解析三&#xff08;metadataAvailability的含义&#xff09; Cesium源码解析四&#xff08;metadata元数据拓展…