环信拉取聊天记录并解析

环信返回的聊天记录文件下载地址下载的文件是.gz格式的压缩文件。如果直接下载的话输出流创建的文件必须是.gz格式压缩文件,否则会乱码。我这里是直接下载、解压、写入内存、读取写入内存的文件、转换字符串、解析json字符串为对象(解析json字符串使用了lombok和GsonFormat插件生成ChatMessageHistory类和DownLoadMessageUrl类)一起完成的。

代码实现

/**
*日期格式:yyyyMMddHH
*String date 历史消息日期 列如:"2021042422"
*/
public void getMessage(String date){
OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url("https://a1.easemob.com/#{Orgname}/#{Appname}/chatmessages/"+date)
.header("Content-Type","application/json")
.header("Authorization","Bearer #{token}")
.get()
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("onFailure3: " + e.getMessage());
}

@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.protocol() + ":" +response.code() + ": " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
System.out.println(headers.name(i) + ":" + headers.value(i));
}
//请求成功,获得json字符串
String messageUrlJson = response.body().string();
//解析json字符串
DownLoadMessageUrl downLoadMessageUrl = JSON.parseObject(messageUrlJson,DownLoadMessageUrl.class);
System.out.println("解析后得到的地址:"+downLoadMessageUrl.getData().get(0).getUrl());
String messageFileUrl = downLoadMessageUrl.getData().get(0).getUrl();
downLoadFile(messageFileUrl,date);
}
});
}

//下载聊天记录文件.gz并解压
public void downLoadFile(String messageFileUrl,String date){
String sourcedir = "G:\\test\\"+date+".gz";

OkHttpClient okHttpClient = new OkHttpClient();
Request request = new Request.Builder()
.url(messageFileUrl)
.get()
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.out.println("downLoadFile: " + e.getMessage());
}

@Override
public void onResponse(Call call, Response response) throws IOException {
System.out.println(response.protocol() + ":" +response.code() + " : " + response.message());
Headers headers = response.headers();
for (int i = 0; i < headers.size(); i++) {
System.out.println(headers.name(i) + ":" + headers.value(i));
}
//下载并解压.gz文件
unGzipFile(sourcedir,response);
}
});
}

//下载并解压.gz文件
public void unGzipFile(String sourcedir,Response response) {
String ouputfile = "";
InputStream fin = null;
GZIPInputStream gzin = null;
FileOutputStream fout = null;
try {
//建立gzip压缩文件输入流
fin=response.body().byteStream();
//建立gzip解压工作流
gzin = new GZIPInputStream(fin);
//分割压缩文件存储路径,获得解压后文件的存储路径
ouputfile = sourcedir.substring(0,sourcedir.lastIndexOf('.'));
System.out.println("解压后的文件路径及名称:"+ouputfile);
//建立解压文件输出流
fout = new FileOutputStream(ouputfile);
int num;
byte[] buf=new byte[2048];//建立缓冲字节数组
//将解压后的文件流写入文件
while ((num = gzin.read(buf,0,buf.length)) != -1) {
fout.write(buf,0,num);
}
System.out.println("解压完成");
//解析json字符串文件,ouputfile为文件路径
getHistoryMessages(ouputfile);
} catch (Exception ex){
System.out.println(ex.toString());
}finally {
try {
if (gzin != null){
gzin.close();
}
if (fout != null){
fout.close();
}
if (fin != null){
fin.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return;
}

//将解压后的文件内容转换为字符串(json格式字符串),并解析json字符串
public void getHistoryMessages(String fileName){
InputStream inputStream = null;
try {
inputStream = new FileInputStream(fileName);
String msg = getStreamToStr(inputStream);
System.out.println("解压后的消息字符串:"+msg);
//字符串替换
String str1 = msg.replace("{\"chat_type\""," {\"chat_type\"");
//去除前后两端的空格
String str2 = str1.trim();
//字符串分割
String[] strings = str2.split(" ");
//将json格式字符串转化为对象
List<ChatMessageHistory> chatMessageHistoryList = new ArrayList<>();
for (int i = 0; i < strings.length; i++) {
ChatMessageHistory chatMessageHistory = JSON.parseObject(strings[i],ChatMessageHistory.class);
chatMessageHistoryList.add(chatMessageHistory);
}
for (int i = 0; i < chatMessageHistoryList.size(); i++) {
System.out.println("第"+(i+1)+"条消息:"+chatMessageHistoryList.get(i).getPayload().getBodies().get(0).getMsg());
}
}catch (IOException e){
e.printStackTrace();
}finally {
//关闭字节输入流
if (inputStream != null){
try {
inputStream.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
/**
* 将一个字节输入流转化为字符串
* @param tInputStream
* @return
*/
public String getStreamToStr(InputStream tInputStream) {
if (tInputStream != null) {
InputStreamReader inputStreamReader = null;
BufferedReader tBufferedReader = null;
try {
//将字节输入流转换为字符输入流
inputStreamReader = new InputStreamReader(tInputStream);
//赋予字符流对象缓冲区
tBufferedReader = new BufferedReader(inputStreamReader);
StringBuffer tStringBuffer = new StringBuffer();
String sTempOneLine;
while ((sTempOneLine = tBufferedReader.readLine()) != null) {
tStringBuffer.append(sTempOneLine);
}
return tStringBuffer.toString();
} catch (Exception ex) {
ex.printStackTrace();
}finally {
try {
if (inputStreamReader != null){
inputStreamReader.close();
}
if (tBufferedReader != null){
tBufferedReader.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
return null;
}

注意:#{Orgname}、#{Appname}、#{token}是变量,替换成自己的即可)

注意:InputStream字节输入流是不能复用的,具体知识自行百度补充)