企业微信会话存档:大文件拉取、加密、上传

承接之前的文章企业微信会话存档sdk报错:A fatal error has been detected by the Java Runtime Environment

在之前的那篇文章结尾,我说发现了系统另外一个隐含的bug:企业微信会话存档拉取媒体文件是分片拉取,我的处理方式有问题导致,保存的永远是最后一个分片。

这个问题之所以没有在测试环境复现,是因为测试环境都是拿的一些小文件测试,结果在线上运行一段时间后,就发现,下载下来的文件显然比真实文件小很多。仔细排查了一下才发现是这个问题。

怎么解决呢?既然企业微信的sdk是分片拉取媒体文件的,那么我们就必需对内容进行汇总。但是汇总之前我们得判断文件的大小,如果文件不大,那么直接用ByteArrayOutputStream接收即可;但是如果文件很大,直接用ByteArrayOutputStream可能导致OOM,这里需要使用临时文件接收。

我使用的是weixin-java-cp这个库,所以代码用这个库的方法演示。
对于小文件,使用ByteArrayOutputStream接收:

ByteArrayOutputStreamByteConsumer byteArrayOutputStreamByteConsumer = new ByteArrayOutputStreamByteConsumer(bos);
msgAuditService.getMediaFile(sdk, sdkFileId, null, null, 180L, byteArrayOutputStreamByteConsumer);

这里我们抽象了一个ByteArrayOutputStreamByteConsumer类,每拉一次分片都会调用这个类,往bos中写分片数据。

public class ByteArrayOutputStreamByteConsumer implements Consumer<byte[]> {private final ByteArrayOutputStream bos;public ByteArrayOutputStreamByteConsumer(ByteArrayOutputStream bos) {this.bos = bos;}@Overridepublic void accept(byte[] bytes) {try {bos.write(bytes);} catch (IOException e) {throw new MsgFileException("写入ByteArrayOutputStream失败", e);}}
}

如果文件比较大,我们需要写入临时文件,使用hutool的工具类创建临时文件。

File tempFile = FileUtil.createTempFile("audit_media_", "." + StringUtils.defaultString(ext, "bin"), false);
msgAuditService.getMediaFile(sdk, sdkFileId, null, null, 180L, tempFile.getAbsolutePath());

至此,我们已经解决文件下载的问题,我们总结一下:

  • 小文件:用ByteArrayOutputStream接收
  • 大文件:用临时文件接收

下载问题只是第一个问题,还有两个问题等着我们。

第二个问题就是文件加密的问题。由于我们的项目媒体文件存在云存储,所以要求上传前必须加密,防止文件泄露。如果你们没有这个需要,那就忽略这个问题。

我之前的加密方式使用的是AES/ECB/PKCS5Padding这种模式,因为使用的是hutool的工具类,默认AES就是这个模式。
之前的做法是拿到文件的byte[],然后对它加密。如果文件很大,比如几个G,那很容易就OOM,为啥之前没有OOM呢,因为第一个问题导致文件内容只有最后一个分片的大小,所以这个问题被隐藏了。

所以现在就不能这么干了,可以使用AES/CTR/NoPadding这种模式代替,这种模式非常适合大文件的加解密。不用一次性传入整个文件的内容,可以流式的进行处理。算法的原理可以自行搜索,这里就不赘述了。

jdk提供的CipherOutputStream可以简化操作:

try (is; CipherOutputStream cos = new CipherOutputStream(os, encryptCipher)) {while (true) {byte[] buffer = new byte[8192];int read = is.read(buffer, 0, 8192);if (read == -1) {break;}cos.write(buffer, 0, read); // 这里write的时候就会同时进行加密}} catch (IOException e) {throw new FileUploadException("文件加密过程失败", e);}

这里的encryptCipherCipher的实例:

private Cipher getCipher(String key, byte[] ivBytes) {SecureRandom secureRandom = new SecureRandom();secureRandom.nextBytes(ivBytes);IvParameterSpec ivParameterSpec = new IvParameterSpec(ivBytes);SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "AES");Cipher encryptCipher;try {encryptCipher = Cipher.getInstance("AES/CTR/NoPadding");encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);} catch (Exception e) {throw new FileUploadException("加密套件初始化失败", e);}return encryptCipher;
}

对于一个大文件,你可以创建一个临时文件来接收加密后的文件,以免OOM。

现在我们解决了第二个问题,大文件加密问题。接下来解决第三个问题,当前文件比较大时,上传非常慢。解决的办法,就是使用分片上传,这个要看各家云存储对分片上传的支持了。阿里的OSS,分片上传文档。

至此,问题完美解决。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IP地址如何保护网络安全

面对网络攻击时&#xff0c;仅依靠常态化的网络安全防御系统已捉襟见肘&#xff0c;如联合使用IP地址数据可以形成多元化的安全解决方案&#xff0c;全面监控网络活动&#xff0c;发现潜在威胁&#xff0c;制定有针对性的应对措施。 网络攻击追踪 当网站或应用遭受DDoS等网络攻…

Helm 简介:Kubernetes 的包管理器

简介 将应用程序部署到 Kubernetes&#xff08;一个功能强大且流行的容器编排系统&#xff09;可能会很复杂。设置单个应用程序可能涉及创建多个相互依赖的 Kubernetes 资源&#xff0c;例如 pods、services、deployments 和 replicasets&#xff0c;每个资源都需要编写详细的…

基于YOLOv8的暗光低光环境下(ExDark数据集)检测,加入多种优化方式---DCNv4结合SPPF ,助力自动驾驶(一)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍了暗光低光数据集检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析&#xff0c;以及如何优化提升检测性能。 &#x1f4a1;&#x1f4a1;&#x1f4a1;加入 DCNv4结合SPPF mAP0.5由原始的0.682提升至…

在 VMware 虚拟机上安装 CentOS系统 完整(全图文)教程

一、前期准备&#xff1a; 1.安装VMware 虚拟机软件&#xff08;不在讲解&#xff0c;可自行去下载安装&#xff09;。官网&#xff1a;https://customerconnect.vmware.com/cn/downloads/details?downloadGroupWKST-PLAYER-1750&productId1377&rPId111471 2.下载iso…

【AWS】step-functions服务编排

文章目录 step-functionsState machine typeStandard workflowsExpress workflows design skillsError handlingsaga Transaction processing控制分布式系统中的并发性 收费 作为AWS Serverless无服务器的一个重要一环 使用step-functions方法将 AWS 服务链接在一起 step-funct…

用python编写爬虫,爬取二手车信息+实验报告

题目 报告要求 工程报告链接放在这里 https://download.csdn.net/download/Samature/88805518使用 1.安装jupyter notebook 2.用jupyter notebook打开工程里的ipynb文件&#xff0c;再run all就行 注意事项 可能遇到的bug 暂无&#xff0c;有的话私信我

如何决定K8S Pod的剔除优先级

在Kubernetes&#xff08;k8s&#xff09;中&#xff0c;当节点资源面临压力时&#xff0c;如何决定Pod的优先级是一个关键问题。在Kubernetes 1.8版本之后&#xff0c;引入了基于Pod优先级的调度策略&#xff0c;即Pod Priority Preemption。这种策略允许在资源不足的情况下&a…

iOS平台如何实现低延迟RTSP转RTMP推送?

技术背景 好多开发者都知道我们有Windows、Android、Linux平台的RTSP转RTMP推送模块&#xff0c;实际上&#xff0c;iOS平台我们也有&#xff0c;并在2016年就已发布。我们都知道&#xff0c;一个好的RTSP转RTMP推送模块&#xff0c;需要足够稳定的前提下&#xff0c;还要低延…

Unity 接口、抽象类、具体类对象的配合使用案例

文章目录 示例1&#xff1a;接口&#xff08;Interface&#xff09;示例2&#xff1a;抽象类&#xff08;Abstract Class&#xff09;示例3&#xff1a;结合使用接口与抽象类示例4&#xff1a;多接口实现示例5&#xff1a;抽象类与接口结合 在Unity中使用C#编程时&#xff0c;接…

制作耳机壳的UV树脂耳机壳UV胶和塑料材质有什么不同?

制作耳机壳的UV树脂和塑料材质在以下几个方面存在区别&#xff1a; 硬度与耐磨性&#xff1a;UV树脂具有较高的硬度和耐磨性&#xff0c;能够有效保护耳机内部零件&#xff0c;延长耳机使用寿命。而塑料材质相对较软&#xff0c;容易受到磨损。透明度与光泽度&#xff1a;UV树…

JAVA中的单例模式->懒汉式

一、步骤 1.构造器私有化>防止直接new private Cat(String name) {System.out.println("构造器被调用");this.name name;} 2.类的内部创建对象 private static Cat cat; 3.向外暴露一个静态的公共方法。getInstance public static Cat getInstance(){if (cat…

es6模块化导入导出与commonjs模块化(nodejs导入导出)详解——导出export

博主的桌面工具软件已经正式开发&#xff0c;获取方式&#xff1a; 可以关注我的小程序【中二少年工具箱】获取。&#xff08;若小程序更新有延迟&#xff0c;或关注小程序后续功能&#xff0c;可先收藏小程序&#xff09; 通过下载链接 百度网盘: 链接&#xff1a;https://p…

【SpringBoot】application配置(5)

type-aliases-package: com.rabbiter.cm.domaintype-aliases-package: 这个配置用于指定mybatis的别名&#xff0c;别名是一个简化的方式&#xff0c;让你在Mapper xml 文件中引用java类型&#xff0c;而不需要使用使用完整的类名。例如&#xff0c;如果你在 com.rabbiter.cm.d…

pymunk初步:设置重力

文章目录 官方示例可视化 官方示例 pymunk是一款2D物理引擎&#xff0c;在游戏开发中十分有用。安装过程无坑 pip install pymunk下面举出官网的一个案例&#xff0c;来简述pymunk的使用流程 import pymunkspace pymunk.Space() space.gravity 0,-981body pymunk.Body() …

Vue组件通信的方式

文章目录 props 父传子$emit 子传父事件总线&#xff08;Event Bus&#xff09;使用Vuex\Pinia状态管理库使用provide/inject props 父传子 父组件向子组件传递数据&#xff1a;通过props属性将数据从父组件传递给子组件。 <template> <div> <child-compone…

邮件群发系统怎么用呢?专业的邮件群发器?

邮件群发系统哪个比较好&#xff1f;邮件营销系统的效果怎么样&#xff1f; 在现代商业活动中&#xff0c;邮件群发系统已成为企业营销的重要工具。那么&#xff0c;邮件群发系统究竟如何使用呢&#xff1f;接下来&#xff0c;蜂邮EDM将为您详细解析邮件群发系统的使用方法。 …

股市反转数据分析

20240206是一个很好的股市反转数据分析的样本。因为之前的1月份2月前3个交易日也就是2月1日&#xff0c;2月2日和2月5日基本都是大跌。数据记录如下&#xff1a; 指数名称指数代码收盘价 [日期] 20231229 [单位] 元收盘价 [日期] 20240205 [单位] 元区间涨跌幅上证指数000001.…

深度学习图像分类相关概念简析+个人举例3(CNN相关补充,附详细举例代码1)

【1】激活函数&#xff08;Activation Function&#xff09;&#xff1a;在深度学习&#xff08;CNN&#xff09;中&#xff0c;激活函数用于引入非线性性质&#xff0c;帮助模型学习复杂的关系。常见的激活函数有ReLU、Sigmoid和Tanh等。 &#xff08;1&#xff09;ReLU激活函…

Godot 游戏引擎个人评价和2024年规划(无代码)

文章目录 前言Godot C# .net core 开发简单评价Godot相关网址可行性 Godot(GDScirpt) Vs CocosGodot VS UnityUnity 的裁员Unity的股票Unity的历史遗留问题&#xff1a;Mono和.net core.net core的开发者&#xff0c;微软 个人的独立游戏Steam平台分成说明独立游戏的选题美术风…

C# CAD交互界面-自定义面板集-添加快捷命令(五)

运行环境 vs2022 c# cad2016 调试成功 一、引用 using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Runtime; using Autodesk.AutoCAD.Windows; using System; using System.Drawing; using System.Windows.Forms; 二、代码说明 [CommandMethod("Cre…