Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

企业微信会话存档获取媒体数据,添加传入lambda函数的方法来遍历媒体数据分片。 #2858

Merged
merged 2 commits into from
Oct 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import me.chanjar.weixin.cp.bean.msgaudit.*;

import java.util.List;
import java.util.function.Consumer;

/**
* 会话内容存档接口.
Expand Down Expand Up @@ -72,6 +73,22 @@ WxCpChatModel getDecryptData(@NonNull long sdk, @NonNull WxCpChatDatas.WxCpChatD
void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout,
@NonNull String targetFilePath) throws WxErrorException;

/**
* 获取媒体文件 传入一个lambda,each所有的数据分片byte[],更加灵活
* 针对图片、文件等媒体数据,提供sdk接口拉取数据内容。
* 详情可以看官方文档,亦可阅读此接口源码。
*
* @param sdk getChatDatas()获取到的sdk,注意,每次获取的sdk会不一样
* @param sdkfileid 消息体内容中的sdkfileid信息
* @param proxy 使用代理的请求,需要传入代理的链接。如:socks5://10.0.0.1:8081 或者 http://10.0.0.1:8081,如果没有传null
* @param passwd 代理账号密码,需要传入代理的账号密码。如 user_name:passwd_123,如果没有传null
* @param timeout 超时时间,分片数据需累加到文件存储。单次最大返回512K字节,如果文件比较大,自行设置长一点,比如timeout=10000
* @param action 传入一个lambda,each所有的数据分片
* @throws WxErrorException the wx error exception
*/
void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout,
@NonNull Consumer<byte[]> action) throws WxErrorException;

/**
* 获取会话内容存档开启成员列表
* 企业可通过此接口,获取企业开启会话内容存档的成员列表
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Consumer;

import static me.chanjar.weixin.cp.constant.WxCpApiPathConsts.MsgAudit.*;

Expand Down Expand Up @@ -80,10 +81,10 @@ public WxCpChatDatas getChatDatas(long seq, @NonNull long limit, String proxy, S
long sdk = Finance.NewSdk();
//因为会话存档单独有个secret,优先使用会话存档的secret
String msgAuditSecret = cpService.getWxCpConfigStorage().getMsgAuditSecret();
if(StringUtils.isEmpty(msgAuditSecret)) {
if (StringUtils.isEmpty(msgAuditSecret)) {
msgAuditSecret = cpService.getWxCpConfigStorage().getCorpSecret();
}
long ret = Finance.Init(sdk, cpService.getWxCpConfigStorage().getCorpId(),msgAuditSecret);
long ret = Finance.Init(sdk, cpService.getWxCpConfigStorage().getCorpId(), msgAuditSecret);
if (ret != 0) {
Finance.DestroySdk(sdk);
throw new WxErrorException("init sdk err ret " + ret);
Expand Down Expand Up @@ -181,7 +182,26 @@ public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String pr
if (!targetFile.getParentFile().exists()) {
targetFile.getParentFile().mkdirs();
}
this.getMediaFile(sdk, sdkfileid, proxy, passwd, timeout, i -> {
try {
// 大于512k的文件会分片拉取,此处需要使用追加写,避免后面的分片覆盖之前的数据。
FileOutputStream outputStream = new FileOutputStream(targetFile, true);
outputStream.write(i);
outputStream.close();
} catch (Exception e) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RESOURCE_LEAK: resource of type java.io.FileOutputStream acquired to outputStream by call to FileOutputStream(...) at line 188 is not released after line 191.
Note: potential exception at line 189


ℹ️ Learn about @sonatype-lift commands

You can reply with the following commands. For example, reply with @sonatype-lift ignoreall to leave out all findings.

Command Usage
@sonatype-lift ignore Leave out the above finding from this PR
@sonatype-lift ignoreall Leave out all the existing findings from this PR
@sonatype-lift exclude <file|issue|path|tool> Exclude specified file|issue|path|tool from Lift findings by updating your config.toml file

Note: When talking to LiftBot, you need to refresh the page to see its response.
Click here to add LiftBot to another repo.


Was this a good recommendation?
[ 🙁 Not relevant ] - [ 😕 Won't fix ] - [ 😑 Not critical, will fix ] - [ 🙂 Critical, will fix ] - [ 😊 Critical, fixing now ]

e.printStackTrace();
}
});
}

@Override
public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String proxy, String passwd, @NonNull long timeout, @NonNull Consumer<byte[]> action) throws WxErrorException {
/**
* 1、媒体文件每次拉取的最大size为512k,因此超过512k的文件需要分片拉取。
* 2、若该文件未拉取完整,sdk的IsMediaDataFinish接口会返回0,同时通过GetOutIndexBuf接口返回下次拉取需要传入GetMediaData的indexbuf。
* 3、indexbuf一般格式如右侧所示,”Range:bytes=524288-1048575“:表示这次拉取的是从524288到1048575的分片。单个文件首次拉取填写的indexbuf
* 为空字符串,拉取后续分片时直接填入上次返回的indexbuf即可。
*/
String indexbuf = "";
int ret, data_len = 0;
log.debug("正在分片拉取媒体文件 sdkFileId为{}", sdkfileid);
Expand All @@ -200,9 +220,7 @@ public void getMediaFile(@NonNull long sdk, @NonNull String sdkfileid, String pr

try {
// 大于512k的文件会分片拉取,此处需要使用追加写,避免后面的分片覆盖之前的数据。
FileOutputStream outputStream = new FileOutputStream(new File(targetFilePath), true);
outputStream.write(Finance.GetData(mediaData));
outputStream.close();
action.accept(Finance.GetData(mediaData));
} catch (Exception e) {
e.printStackTrace();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@
import me.chanjar.weixin.cp.demo.WxCpDemoInMemoryConfigStorage;
import me.chanjar.weixin.cp.util.xml.XStreamTransformer;
import org.eclipse.jetty.util.ajax.JSON;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -39,17 +42,21 @@ public class WxCpMsgAuditTest {
*/
// com.binarywang.spring.starter.wxjava.cp.config.WxCpServiceAutoConfiguration
// WxCpServiceImpl.getAccessToken()
@Test
public void test() throws Exception {

InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream);

wxCpConfigStorage = config;
cpService = new WxCpServiceImpl();
cpService.setWxCpConfigStorage(config);

@BeforeTest
private void initCpservice() {
if(cpService == null) {
InputStream inputStream = ClassLoader.getSystemResourceAsStream("test-config.xml");
WxCpDemoInMemoryConfigStorage config = WxCpDemoInMemoryConfigStorage.fromXml(inputStream);
config.setMsgAuditLibPath("/E:/IDEA_WORKSPACE/saisc/crs-member-java/target/classes/wework/libcrypto-1_1-x64.dll,libssl-1_1-x64.dll,libcurl-x64.dll,WeWorkFinanceSdk.dll");
binarywang marked this conversation as resolved.
Show resolved Hide resolved
wxCpConfigStorage = config;
cpService = new WxCpServiceImpl();
cpService.setWxCpConfigStorage(config);
}
}

@Test
public void test() throws Exception {
/**
* 客户同意进行聊天内容存档事件回调
* 配置了客户联系功能的成员添加外部联系人同意进行聊天内容存档时,回调该事件。
Expand Down Expand Up @@ -644,9 +651,109 @@ public void test() throws Exception {
* https://www.jianshu.com/p/dde171887d63
*/
String getUrl = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s";
String data = cpService.get(String.format(getUrl, config.getCorpId(), config.getCorpSecret()), null);
String data = cpService.get(String.format(getUrl, wxCpConfigStorage.getCorpId(), wxCpConfigStorage.getCorpSecret()), null);


}

@Test
public void testGetMediaFile() throws Exception {
WxCpMsgAuditService msgAuditService = cpService.getMsgAuditService();
WxCpChatDatas chatDatas = msgAuditService.getChatDatas(0L, 100L, null, null, 10);
for (WxCpChatDatas.WxCpChatData chatDatum : chatDatas.getChatData()) {
WxCpChatModel decryptData = msgAuditService.getDecryptData(chatDatas.getSdk(), chatDatum, 2);
// 文件后缀
String suffix = "";
// 文件名md5
String md5Sum = "";
// sdkFileId
String sdkFileId = "";
String msgType = decryptData.getMsgType();
if(msgType == null ) msgType = "";
switch (msgType) {
case "image":
suffix = ".jpg";
md5Sum = decryptData.getImage().getMd5Sum();
sdkFileId = decryptData.getImage().getSdkFileId();
break;
case "voice":
suffix = ".amr";
md5Sum = decryptData.getVoice().getMd5Sum();
sdkFileId = decryptData.getVoice().getSdkFileId();
break;
case "video":
suffix = ".mp4";
md5Sum = decryptData.getVideo().getMd5Sum();
sdkFileId = decryptData.getVideo().getSdkFileId();
break;
case "emotion":
md5Sum = decryptData.getEmotion().getMd5Sum();
sdkFileId = decryptData.getEmotion().getSdkFileId();
int type = decryptData.getEmotion().getType();
switch (type) {
case 1:
suffix = ".gif";
break;
case 2:
suffix = ".png";
break;
default:
return;
}
break;
case "file":
md5Sum = decryptData.getFile().getMd5Sum();
suffix = "." + decryptData.getFile().getFileExt();
sdkFileId = decryptData.getFile().getSdkFileId();
break;
// 音频存档消息
case "meeting_voice_call":

md5Sum = decryptData.getVoiceId();
sdkFileId = decryptData.getMeetingVoiceCall().getSdkFileId();
for (WxCpChatModel.MeetingVoiceCall.DemoFileData demofiledata :
decryptData.getMeetingVoiceCall().getDemoFileData()) {
String demoFileDataFileName = demofiledata.getFileName();
suffix = demoFileDataFileName.substring(demoFileDataFileName.lastIndexOf(".") + 1);
}

break;
// 音频共享文档消息
case "voip_doc_share":

md5Sum = decryptData.getVoipId();
WxCpFileItem docShare = decryptData.getVoipDocShare();
String fileName = docShare.getFileName();
suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
break;
default:
continue;
}

/**
* 拉取媒体文件
*
* 传入一个each函数,用于遍历每个分片的数据
*/
String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
String targetPath = path + "testfile/" + md5Sum + suffix;
File file = new File(targetPath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}else{
file.delete();
}
cpService.getMsgAuditService().getMediaFile(chatDatas.getSdk(), sdkFileId, null, null, 1000L, data -> {
try {
// 大于512k的文件会分片拉取,此处需要使用追加写,避免后面的分片覆盖之前的数据。
FileOutputStream outputStream = new FileOutputStream(targetPath, true);
outputStream.write(data);
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
});
}
Finance.DestroySdk(chatDatas.getSdk());
}
}
1 change: 1 addition & 0 deletions weixin-java-cp/src/test/resources/test-config.sample.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<oauth2redirectUri>网页授权获取用户信息回调地址</oauth2redirectUri>
<webhookKey>webhook链接地址的key值</webhookKey>
<!-- 企业微信会话存档,私钥,windows以及linux环境sdk路径 -->
<msgAuditSecret>会话存档的secret</msgAuditSecret>
<msgAuditPriKey>-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQCTfm5cxqfglfOV7b/Z7OtTZZoZpk2EPTvVhn/ngsfKR899xRdR
25s4h8HkK0XhxqYdOGoAdG3Gms+DvCSY/vu3UtImf0eZSNXpKZJBUnvUVjX4ivnr
Expand Down