当前位置: 首页 > news >正文

环信服务端下载消息文件---菜鸟教程

前言

在服务端,下载消息文件是一个重要的功能。它允许您从服务器端获取并保存聊天消息、文件等数据,以便在本地进行进一步的处理和分析。本指南将指导您完成环信服务端下载消息文件的步骤。
环信服务端下载消息文件是指在环信服务端上,通过调用相应的API接口,从服务器端下载聊天消息、文件等数据的过程。因环信服务端保存的消息漫游是有时间限制,有用户需要漫游全部的消息或者自己服务端做所有消息记录的备份。可以从环信服务端下载消息文件来进行解压,读取消息文件内容进行存储到自己的服务端。

前提条件

  • 已在环信即时通讯控制台 开通配置环信即时通讯 IM 服务。
    注册环信即时通讯IM
  • 了解环信 IM REST API 的调用频率限制
  • 环信接口文档介绍:

一、下载消息文件

以下将介绍如何通过环信接口获取到的URL来进行下载文件,解压文件,读取文件。
注:
time参数: 历史消息记录查询的起始时间。UTC 时间,使用 ISO8601 标准,格式为 yyyyMMddHH。例如 time 为 2018112717,则表示查询 2018 年 11 月 27 日 17 时至 2018 年 11 月 27 日 18 时期间的历史消息。若海外集群为 UTC 时区,需要根据自己所在的时区进行时间转换。
在这里插入图片描述
上图是环信官方文档中给出的获取历史消息记录响应示例。从示例中可以看出我们请求以后可以得到一个URL,这个URL为消息文件的下载URL。

1、下载消息文件环信rest 接口请求代码如下:
String url = "https://{{RestApi}}/{{org_name}}/{{app_name}}/chatmessages/2023122010";
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Type","application/json");
headers.add("Authorization","Bearer Authorization");
Map<String, String> body = new HashMap<>();
HttpEntity<Map<String, String>> entity = new HttpEntity<>(body, headers);
ResponseEntity<Map> response;
try {response = restTemplate.exchange(url, HttpMethod.GET, entity, Map.class);System.out.print("消息文件下载成功---"+response.toString());
} catch (Exception e) {System.out.print("消息文件下载失败---"+e.toString());
}
2、消息文件下载,通过请求环信下载历史消息文件接口获取到的URL 进行下载。

示例代码:

String url = "";
String targetUrl = "";
download(url,targetUrl);
/** 
* 根据url下载文件,保存到filepath中 
* 
* @param url 文件的url 
* @param diskUrl 本地存储路径 
* @return 
*/
public static String download(String url, String diskUrl) {String filepath = "";String filename = "";try {HttpClient client = HttpClients.createDefault();HttpGet httpget = new HttpGet(url);// 加入Referer,防止防盗链        httpget.setHeader("Referer", url);HttpResponse response = client.execute(httpget);HttpEntity entity = response.getEntity();InputStream is = entity.getContent();if (StringUtils.isBlank(filepath)){Map<String,String> map = getFilePath(response,url,diskUrl);filepath = map.get("filepath");filename = map.get("filename");}File file = new File(filepath);file.getParentFile().mkdirs();FileOutputStream fileout = new FileOutputStream(file);byte[] buffer = new byte[cache];int ch = 0;while ((ch = is.read(buffer)) != -1) {fileout.write(buffer, 0, ch);}is.close();fileout.flush();fileout.close();} catch (Exception e) {e.printStackTrace();}return filename;
}/** 
* 获取response要下载的文件的默认路径 
** @param response* @return */public static Map<String,String> getFilePath(HttpResponse response, String url, String diskUrl) {Map<String,String> map = new HashMap<>();String filepath = diskUrl;String filename = getFileName(response, url);String contentType = response.getEntity().getContentType().getValue();if(StringUtils.isNotEmpty(contentType)){// 获取后缀        String regEx = ".+(.+)$";Pattern p = Pattern.compile(regEx);Matcher m = p.matcher(filename);if (!m.find()) {// 如果正则匹配后没有后缀,则需要通过response中的ContentType的值进行匹配                filename = filename +".gz";}else{if(filename.length()>20){filename = getRandomFileName() + ".gz";}}}if (filename != null) {filepath += filename;} else {filepath += getRandomFileName();}map.put("filename", filename);map.put("filepath", filepath);return map;
}/*** 获取response header中Content-Disposition中的filename值* @param response * @param url* @return*/public static String getFileName(HttpResponse response,String url) {Header contentHeader = response.getFirstHeader("Content-Disposition");String filename = null;if (contentHeader != null) {// 如果contentHeader存在        HeaderElement[] values = contentHeader.getElements();if (values.length == 1) {NameValuePair param = values[0].getParameterByName("filename");if (param != null) {try {filename = param.getValue();} catch (Exception e) {e.printStackTrace();}}}}else{// 正则匹配后缀        filename = getSuffix(url);}return filename;
}/** 
* 获取随机文件名 
* 
* @return 
*/
public static String getRandomFileName() {return String.valueOf(System.currentTimeMillis());
}/** 
* 获取文件名后缀 
* @param url 
* @return 
*/
public static String getSuffix(String url) {// 正则表达式“.+/(.+)$”的含义就是:被匹配的字符串以任意字符序列开始,后边紧跟着字符“/”,    // 最后以任意字符序列结尾,“()”代表分组操作,这里就是把文件名做为分组,匹配完毕我们就可以通过Matcher    // 类的group方法取到我们所定义的分组了。需要注意的这里的分组的索引值是从1开始的,所以取第一个分组的方法是m.group(1)而不是m.group(0)。    String regEx = ".+/(.+)$";Pattern p = Pattern.compile(regEx);Matcher m = p.matcher(url);if (!m.find()) {// 格式错误,则随机生成个文件名        return String.valueOf(System.currentTimeMillis());}return m.group(1);}
  • url为第一步中从环信下载历史消息文件接口中请求返回的url(消息文件下载地址)
  • targetUrl 为下载的本地存储路径

下载以后从对应的路径下就可以看到所下载的文件。
在这里插入图片描述

3、消息文件解压,下载完的文件是以.gz结尾的压缩文件,需要对压缩文件进行解压
 public static void unGzipFile(String gzFilePath,String directoryPath) {String ouputfile = "";try {//建立gzip压缩文件输入流            FileInputStream fin = new FileInputStream(gzFilePath);//建立gzip解压工作流            GZIPInputStream gzin = new GZIPInputStream(fin);//建立解压文件输出流//              ouputfile = sourcedir.substring(0,sourcedir.lastIndexOf('.'));//              ouputfile = ouputfile.substring(0,ouputfile.lastIndexOf('.'));            FileOutputStream fout = new FileOutputStream(directoryPath);int num;byte[] buf=new byte[1024];while ((num = gzin.read(buf,0,buf.length)) != -1) {fout.write(buf,0,num);}gzin.close();fout.close();fin.close();} catch (Exception ex){System.err.println(ex.toString());}return;}

gzFilePath:压缩文件路径
directoryPath:加压到的文件目录路径
解压后的文件如下图所示:
在这里插入图片描述

4、文件读取,将解压后的文件读取出来
FileInputStream inputStream = null;
try {inputStream = new FileInputStream("/Users/liupeng/Downloads/download/1234567890");BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));String str = null;long i = 0;while(true){try {if (!((str = bufferedReader.readLine()) != null)) break;} catch (IOException e) {e.printStackTrace();}JSONObject jo = JSONObject.parseObject(str);System.out.println("==========================================" + i);System.out.println("消息id:" + jo.get("msg_id"));System.out.println("发送id:" + jo.get("from"));System.out.println("接收id:" + jo.get("to"));System.out.println("服务器时间戳:" + jo.get("timestamp"));System.out.println("会话类型:" + jo.get("chat_type"));System.out.println("消息扩展:" + jo.getJSONObject("payload").get("ext"));System.out.println("消息体:" + jo.getJSONObject("payload").getJSONArray("bodies").get(0));i ++;if (i > 100) break;}//close    try {inputStream.close();bufferedReader.close();} catch (IOException e) {e.printStackTrace();}} catch (FileNotFoundException e) {e.printStackTrace();
}

解析完以后日志打印如下:
在这里插入图片描述
至此,解析完以后可以将解析的数据进行存储。

相关文档:

注册环信即时通讯IM:https://console.easemob.com/user/register

环信IM集成文档:https://docs-im-beta.easemob.com/document/ios/quickstart.html

IMGeek社区支持:https://www.imgeek.net/

相关文章:

环信服务端下载消息文件---菜鸟教程

前言 在服务端&#xff0c;下载消息文件是一个重要的功能。它允许您从服务器端获取并保存聊天消息、文件等数据&#xff0c;以便在本地进行进一步的处理和分析。本指南将指导您完成环信服务端下载消息文件的步骤。 环信服务端下载消息文件是指在环信服务端上&#xff0c;通过调…...

创建型模式 | 建造者模式

一、建造者模式 1、原理 建造者模式又叫生成器模式&#xff0c;是一种对象的构建模式。它可以将复杂对象的建造过程抽象出来&#xff0c;使这个抽象过程的不同实现方法可以构造出不同表现&#xff08;属性&#xff09;的对象。创建者模式是一步一步创建一个复杂的对象&#xf…...

MVC设计模式

在当今的软件开发领域&#xff0c;MVC&#xff08;Model-View-Controller&#xff09;设计模式已经成为了一种广泛使用的架构模式。它为应用程序提供了一种结构化的方法&#xff0c;将数据、用户界面和业务逻辑分开&#xff0c;从而使得应用程序更易于维护、扩展和重用。 一、…...

WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir 错误解决

[TOC](WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir 错误解决) 1. 错误信息 <3>WSL (2103) ERROR: CreateProcessEntryCommon:493: chdir(/mnt/d/Program Files/PowerShell/7) failed 52. 解决方法 wsl --shutdownwslrefer: https://github.com/microsoft/…...

【二、自动化测试】为什么要做自动化测试?哪种项目适合做自动化?

自动化测试是一种软件测试方法&#xff0c;通过编写和使用自动化脚本和工具&#xff0c;以自动执行测试用例并生成结果。 自动化旨在替代手动测试过程&#xff0c;提高测试效率和准确性。 自动化测试可以覆盖多种测试类型&#xff0c;包括功能测试、性能测试、安全测试等&…...

用ChatGPT来造一个ChatGPT:计算机领域智能问答系统实践(2)

在PHP语言中&#xff0c;你可以使用MySQL数据库来存储知识库&#xff0c;并使用PHP来实现系统的逻辑。以下是一个简单的示例&#xff1a; 创建数据库表&#xff1a; 首先&#xff0c;创建一个名为 computer_knowledge 的表来存储计算机知识。可以使用以下SQL语句&#xff1a;…...

Ubuntu开机自动挂载硬盘

前言&#xff1a; 因为我的电脑是WIN10 Ubuntu18.04双系统&#xff0c;且两个系统都装在C盘上&#xff0c;而D盘作为数据和代码存储盘&#xff0c;经常会开机就被访问&#xff0c;例如上一次关机前用VS Code访问D盘代码&#xff0c;然后下一次开机的时候打开VSCode发现打不开…...

vue3基础:单文件组件介绍

介绍 Vue 的单文件组件 (即 *.vue 文件&#xff0c;简称 SFC&#xff0c;全称是single file component) 是一种特殊的文件格式&#xff0c;使我们能够将一个 Vue 组件的模板、逻辑与样式封装在单个文件中。下面是一个单文件组件的示例&#xff1a; <script> export def…...

OCR字符识别:开始批量识别身份证信息

身份证信息批量识别OCR是一项解决方案&#xff0c;它能够将身份证照片打包成zip格式或通过URL地址进行提交&#xff0c;并能够识别照片中的文本信息。最终&#xff0c;用户可以将识别结果生成为excel文件进行下载。 API接口功能&#xff1a; 1. 批量识别&#xff1a;支持将多…...

php多小区智慧物业管理系统源码带文字安装教程

多小区智慧物业管理系统源码带文字安装教程 运行环境 服务器宝塔面板 PHP 7.0 Mysql 5.5及以上版本 Linux Centos7以上 统计分析以小区为单位&#xff0c;统计如下数据&#xff1a;小区总栋数、小区总户数、小区总人数、 小区租户数量、小区每月收费金额统计、小区车位统计、小…...

解决虚拟机的网络图标不见之问题

在WIN11中&#xff0c;启动虚拟机后&#xff0c;发现网络图标不见了&#xff0c;见下图&#xff1a; 1、打开虚拟机终端 输入“sudo server network-manager stop”&#xff0c;停止网络管理器 输入“cd /回车” &#xff0c; 切换到根目录 输入“cd var回车” &#xff0c;…...

【Spring类路径Bean定义信息扫描】

Spring类路径Bean定义信息扫描 1. ClassPathBeanDefinitionScanner作用2. 类声明3. 属性4. 构造器5. 扫描方法6. 真正扫描方法7. postProcessBeanDefinition8. 注册bean定义 1. ClassPathBeanDefinitionScanner作用 扫描类路径下的类注册为bean定义。2. 类声明 public class …...

Ubuntu上安装VMware+win11系统手册

Ubuntu安装vmware 下载&#xff1a; Linux 版下载地址&#xff1a;https://www.vmware.com/go/getworkstation-linux 安装&#xff1a; sudo chmod x VMware-Workstation-Full-17.5.0-22583795.x86_64.bundle 执行安装命令&#xff1a; sudo ./VMware-Workstation-Full-17.5.0…...

2024年1月12日:清爽无糖rio留下唇齿之间的香甜

友利奈绪的时间管理 2024年1月12日08:02:28进行java程序设计的上课准备 2024年1月12日08:02:44知道java的题目有18道 2024年1月12日08:43:07随机数去重比较 2024年1月12日08:54:03C语言题目最小公倍数 2024年1月12日08:58:37C语言题目二维数组变一维数组 2024年1月12日10…...

群晖Synology Drive同步文件时过滤指定文件夹“dist“, “node_modules“

群晖Synology Drive同步文件时过滤指定文件夹"dist", “node_modules” mac用户 安装Synology Drive创建同步任务修改Synology Drive配置 打开/Users/[用户名]/Library/Application Support/SynologyDrive/data/session/[同步任务序号&#xff0c;第一个同步任务就…...

小程序中滚动字幕

需求&#xff1a;在录像时需要在屏幕上提示字幕&#xff0c;整体匀速向上滚动 html部分&#xff1a; <view class"subtitles_main"><view style"font-size:34rpx;color: #fff;line-height: 60rpx;" animation"{{animation}}">人生的…...

MySQL中约束是什么?

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…...

若依在表格中如何将字典的键值转为中文

文章目录 一、需求&#xff1a;二、问题解决步骤1、给需要转换的列绑定formatter属性2、获取字典项3、编写formatter属性绑定的方法 一、需求&#xff1a; 后端有时候返回的是字典的键值&#xff0c;在前端展示时需要转成中文值 后端返回的是dictValue&#xff0c;现在要转换…...

用笨办法-刻意练习来提高自己的编程能力

尝试了很多学习方法&#xff0c;企图快速提高编程能力&#xff0c;但最终发现&#xff0c;唯有老老实实刻意练习1&#xff0c;在辛苦与时间积累下&#xff0c;逐渐提升能力&#xff0c;才是最有效的方式。 将自己的笨办法总结了一下&#xff0c;主要包含7个步骤&#xff1a; …...

FineBI报表页面大屏小屏自适应显示问题

大屏正常显示 显示正常 小屏BI自适应显示 存在遮挡字体情况 小屏浏览器缩放显示 等比缩放后显示正常...

地震勘探——干扰波识别、井中地震时距曲线特点

目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波&#xff1a;可以用来解决所提出的地质任务的波&#xff1b;干扰波&#xff1a;所有妨碍辨认、追踪有效波的其他波。 地震勘探中&#xff0c;有效波和干扰波是相对的。例如&#xff0c;在反射波…...

微信小程序之bind和catch

这两个呢&#xff0c;都是绑定事件用的&#xff0c;具体使用有些小区别。 官方文档&#xff1a; 事件冒泡处理不同 bind&#xff1a;绑定的事件会向上冒泡&#xff0c;即触发当前组件的事件后&#xff0c;还会继续触发父组件的相同事件。例如&#xff0c;有一个子视图绑定了b…...

CTF show Web 红包题第六弹

提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框&#xff0c;很难让人不联想到SQL注入&#xff0c;但提示都说了不是SQL注入&#xff0c;所以就不往这方面想了 ​ 先查看一下网页源码&#xff0c;发现一段JavaScript代码&#xff0c;有一个关键类ctfs…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

1.3 VSCode安装与环境配置

进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件&#xff0c;然后打开终端&#xff0c;进入下载文件夹&#xff0c;键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...

Rapidio门铃消息FIFO溢出机制

关于RapidIO门铃消息FIFO的溢出机制及其与中断抖动的关系&#xff0c;以下是深入解析&#xff1a; 门铃FIFO溢出的本质 在RapidIO系统中&#xff0c;门铃消息FIFO是硬件控制器内部的缓冲区&#xff0c;用于临时存储接收到的门铃消息&#xff08;Doorbell Message&#xff09;。…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制

使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下&#xff0c;限制某个 IP 的访问频率是非常重要的&#xff0c;可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案&#xff0c;使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...