Skip to content

Commit 7416540

Browse files
committed
处理上传多媒体消息
1 parent 3b49a0e commit 7416540

File tree

9 files changed

+273
-18
lines changed

9 files changed

+273
-18
lines changed

pom.xml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@
2929
<artifactId>httpclient</artifactId>
3030
<version>4.5.3</version>
3131
</dependency>
32+
33+
<dependency>
34+
<groupId>org.apache.httpcomponents</groupId>
35+
<artifactId>httpmime</artifactId>
36+
<version>4.5</version>
37+
</dependency>
3238

3339
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
3440
<dependency>
@@ -50,8 +56,18 @@
5056
<artifactId>emoji-java</artifactId>
5157
<version>3.2.0</version>
5258
</dependency>
59+
60+
<!-- https://mvnrepository.com/artifact/javax.activation/activation -->
61+
<dependency>
62+
<groupId>javax.activation</groupId>
63+
<artifactId>activation</artifactId>
64+
<version>1.1.1</version>
65+
</dependency>
66+
67+
5368
</dependencies>
5469

70+
5571
<!-- build all dependencies in one jar -->
5672
<build>
5773
<plugins>

src/main/java/cn/zhouyafeng/itchat4j/api/MessageTools.java

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
package cn.zhouyafeng.itchat4j.api;
22

3+
import java.io.File;
4+
import java.text.SimpleDateFormat;
35
import java.util.Date;
46
import java.util.HashMap;
57
import java.util.Map;
8+
import java.util.Random;
69
import java.util.logging.Logger;
710
import java.util.regex.Matcher;
811

12+
import javax.activation.MimetypesFileTypeMap;
13+
914
import org.apache.http.HttpEntity;
15+
import org.apache.http.entity.ContentType;
16+
import org.apache.http.entity.mime.HttpMultipartMode;
17+
import org.apache.http.entity.mime.MultipartEntityBuilder;
1018
import org.apache.http.util.EntityUtils;
1119

1220
import com.alibaba.fastjson.JSON;
@@ -166,7 +174,155 @@ public static void sendRawMsg(int msgType, String content, String toUserName) {
166174
} catch (Exception e) {
167175
logger.info(e.getMessage());
168176
}
177+
}
178+
179+
/**
180+
* 上传多媒体文件到 微信服务器,目前应该支持3种类型:
181+
* <p>
182+
* 1. pic 直接显示,包含图片,表情
183+
* </p>
184+
* <p>
185+
* 2.video
186+
* </p>
187+
* <p>
188+
* 3.doc 显示为文件,包含PDF等
189+
* </p>
190+
*
191+
* @author https://github.com/yaphone
192+
* @date 2017年5月7日 上午12:41:13
193+
* @param filePath
194+
* @return
195+
*/
196+
private static String uploadMediaToServer(String filePath) {
197+
File f = new File(filePath);
198+
if (!f.exists() && f.isFile()) {
199+
logger.info("file is not exist");
200+
return null;
201+
}
202+
String url = (String) core.getLoginInfo().get("fileUrl") + "/webwxuploadmedia?f=json";
203+
String mimeType = new MimetypesFileTypeMap().getContentType(f);
204+
String mediaType = "";
205+
if (mimeType == null) {
206+
mimeType = "text/plain";
207+
} else {
208+
mediaType = mimeType.split("/")[0].equals("image") ? "pic" : "doc";
209+
}
210+
String lastModifieDate = new SimpleDateFormat("yyyy MM dd HH:mm:ss").format(new Date());
211+
long fileSize = f.length();
212+
String passTicket = (String) core.getLoginInfo().get("pass_ticket");
213+
String clientMediaId = String.valueOf(new Date().getTime())
214+
+ String.valueOf(new Random().nextLong()).substring(0, 4);
215+
String webwxDataTicket = MyHttpClient.getCookie("webwx_data_ticket");
216+
if (webwxDataTicket == null) {
217+
logger.info("get cookie webwx_data_ticket error");
218+
return null;
219+
}
220+
221+
Map<String, Object> paramMap = new HashMap<String, Object>();
222+
@SuppressWarnings("unchecked")
223+
Map<String, Map<String, String>> baseRequestMap = (Map<String, Map<String, String>>) core.getLoginInfo()
224+
.get("baseRequest");
225+
paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest"));
226+
paramMap.put("ClientMediaId", clientMediaId);
227+
paramMap.put("TotalLen", fileSize);
228+
paramMap.put("StartPos", 0);
229+
paramMap.put("DataLen", fileSize);
230+
paramMap.put("MediaType", 4);
231+
232+
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
233+
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
234+
235+
builder.addTextBody("id", "WU_FILE_0", ContentType.TEXT_PLAIN);
236+
builder.addTextBody("name", filePath, ContentType.TEXT_PLAIN);
237+
builder.addTextBody("type", mimeType, ContentType.TEXT_PLAIN);
238+
builder.addTextBody("lastModifieDate", lastModifieDate, ContentType.TEXT_PLAIN);
239+
builder.addTextBody("size", String.valueOf(fileSize), ContentType.TEXT_PLAIN);
240+
builder.addTextBody("mediatype", mediaType, ContentType.TEXT_PLAIN);
241+
builder.addTextBody("uploadmediarequest", JSON.toJSONString(paramMap), ContentType.TEXT_PLAIN);
242+
builder.addTextBody("webwx_data_ticket", webwxDataTicket, ContentType.TEXT_PLAIN);
243+
builder.addTextBody("pass_ticket", passTicket, ContentType.TEXT_PLAIN);
244+
builder.addBinaryBody("filename", f, ContentType.create(mimeType), filePath);
245+
HttpEntity reqEntity = builder.build();
246+
HttpEntity entity = myHttpClient.doPostFile(url, reqEntity);
247+
if (entity != null) {
248+
try {
249+
String result = EntityUtils.toString(entity, "UTF-8");
250+
return JSON.parseObject(result).getString("MediaId");
251+
} catch (Exception e) {
252+
logger.info(e.getMessage());
253+
}
254+
255+
}
256+
return null;
257+
}
169258

259+
/**
260+
* 发送图片消息,内部调用
261+
*
262+
* @author https://github.com/yaphone
263+
* @date 2017年5月7日 下午10:38:55
264+
* @return
265+
*/
266+
private static boolean webWxSendMsgImg(String userId, String mediaId) {
267+
String url = String.format("%s/webwxstatusnotify?lang=zh_CN&pass_ticket=%s", core.getLoginInfo().get("url"),
268+
core.getLoginInfo().get("pass_ticket"));
269+
Map<String, Object> msgMap = new HashMap<String, Object>();
270+
msgMap.put("Type", 3);
271+
msgMap.put("MediaId", mediaId);
272+
msgMap.put("FromUserName", core.getUserSelfList().get(0).getString("UserName"));
273+
msgMap.put("ToUserName", userId);
274+
String clientMsgId = String.valueOf(new Date().getTime())
275+
+ String.valueOf(new Random().nextLong()).substring(1, 5);
276+
msgMap.put("LocalID", clientMsgId);
277+
msgMap.put("ClientMsgId", clientMsgId);
278+
Map<String, Object> paramMap = new HashMap<String, Object>();
279+
@SuppressWarnings("unchecked")
280+
Map<String, Map<String, String>> baseRequestMap = (Map<String, Map<String, String>>) core.getLoginInfo()
281+
.get("baseRequest");
282+
paramMap.put("BaseRequest", baseRequestMap.get("BaseRequest"));
283+
paramMap.put("Msg", msgMap);
284+
String paramStr = JSON.toJSONString(paramMap);
285+
System.out.println(url);
286+
System.out.println(paramStr);
287+
HttpEntity entity = myHttpClient.doPost(url, paramStr);
288+
if (entity != null) {
289+
try {
290+
System.out.println(EntityUtils.toString(entity, "UTF-8"));
291+
} catch (Exception e) {
292+
logger.info(e.getMessage());
293+
}
294+
}
295+
return true;
296+
297+
}
298+
299+
/**
300+
* 根据昵称发送图片消息
301+
*
302+
* @author https://github.com/yaphone
303+
* @date 2017年5月7日 下午10:32:45
304+
* @param nackName
305+
* @return
306+
*/
307+
public static boolean sendPicMsgByNickName(String nickName, String filePath) {
308+
return false;
309+
}
310+
311+
/**
312+
* 根据用户id发送图片消息
313+
*
314+
* @author https://github.com/yaphone
315+
* @date 2017年5月7日 下午10:34:24
316+
* @param nickName
317+
* @param filePath
318+
* @return
319+
*/
320+
public static boolean sendPicMsgByUserId(String userId, String filePath) {
321+
String mediaId = uploadMediaToServer(filePath);
322+
if (mediaId != null) {
323+
return webWxSendMsgImg(userId, mediaId);
324+
}
325+
return false;
170326
}
171327

172328
}

src/main/java/cn/zhouyafeng/itchat4j/components/Login.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ public void processLoginInfo(String loginContent) {
262262
baseRequest.put("Uin", (String) core.getLoginInfo().get("wxuin"));
263263
core.getLoginInfo().put("pass_ticket",
264264
doc.getElementsByTagName("pass_ticket").item(0).getFirstChild().getNodeValue());
265-
baseRequest.put("DeviceID", (String) core.getLoginInfo().get("pass_ticket"));
265+
baseRequest.put("DeviceID", (String) core.getLoginInfo().get("deviceid"));
266266
BaseRequest.put("BaseRequest", baseRequest);
267267
core.getLoginInfo().put("baseRequest", BaseRequest);
268268
}

src/main/java/cn/zhouyafeng/itchat4j/utils/Contact.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
public class Contact {
2020
Logger logger = Logger.getLogger("Contact");
2121
Core core = Core.getInstance();
22-
CloseableHttpClient httpClient = core.getHttpClient();
22+
CloseableHttpClient httpClient = MyHttpClient.getHttpClient();
2323

2424
public List<Object> getContact(boolean update) {
2525
String url = String.format("%s/webwxgetcontact?r=%s&seq=0&skey=%s", core.loginInfo.get("url"),

src/main/java/cn/zhouyafeng/itchat4j/utils/Core.java

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,6 @@
44
import java.util.List;
55
import java.util.Map;
66

7-
import org.apache.http.impl.client.CloseableHttpClient;
8-
import org.apache.http.impl.client.HttpClients;
9-
107
import com.alibaba.fastjson.JSONObject;
118

129
/**
@@ -48,8 +45,8 @@ public static Core getInstance() {
4845
private List<JSONObject> msgList = storageClass.getMsgList();
4946

5047
Map<String, Object> loginInfo = new HashMap<String, Object>();
51-
CloseableHttpClient httpClient = HttpClients.createDefault();
52-
MyHttpClient myHttpClient = new MyHttpClient();
48+
// CloseableHttpClient httpClient = HttpClients.createDefault();
49+
MyHttpClient myHttpClient = MyHttpClient.getInstance();
5350
String uuid = null;
5451

5552
Map<String, Object> functionDict = new HashMap<String, Object>() {
@@ -96,14 +93,6 @@ public void setLoginInfo(Map<String, Object> loginInfo) {
9693
this.loginInfo = loginInfo;
9794
}
9895

99-
public CloseableHttpClient getHttpClient() {
100-
return httpClient;
101-
}
102-
103-
public void setHttpClient(CloseableHttpClient httpClient) {
104-
this.httpClient = httpClient;
105-
}
106-
10796
public String getUuid() {
10897
return uuid;
10998
}

src/main/java/cn/zhouyafeng/itchat4j/utils/MyHttpClient.java

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@
1010
import org.apache.http.Consts;
1111
import org.apache.http.HttpEntity;
1212
import org.apache.http.client.ClientProtocolException;
13+
import org.apache.http.client.CookieStore;
1314
import org.apache.http.client.config.RequestConfig;
1415
import org.apache.http.client.entity.UrlEncodedFormEntity;
1516
import org.apache.http.client.methods.CloseableHttpResponse;
1617
import org.apache.http.client.methods.HttpGet;
1718
import org.apache.http.client.methods.HttpPost;
19+
import org.apache.http.cookie.Cookie;
1820
import org.apache.http.entity.StringEntity;
21+
import org.apache.http.impl.client.BasicCookieStore;
1922
import org.apache.http.impl.client.CloseableHttpClient;
2023
import org.apache.http.impl.client.HttpClients;
2124
import org.apache.http.message.BasicNameValuePair;
@@ -32,10 +35,50 @@
3235
public class MyHttpClient {
3336
private Logger logger = Logger.getLogger("MyHttpClient");
3437

35-
private CloseableHttpClient httpClient = HttpClients.createDefault();
38+
private static CloseableHttpClient httpClient = HttpClients.createDefault();
3639

37-
public MyHttpClient() {
40+
private static MyHttpClient instance = null;
3841

42+
private static CookieStore cookieStore;
43+
44+
static {
45+
cookieStore = new BasicCookieStore();
46+
47+
// 将CookieStore设置到httpClient中
48+
httpClient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
49+
}
50+
51+
public static String getCookie(String name) {
52+
List<Cookie> cookies = cookieStore.getCookies();
53+
for (Cookie cookie : cookies) {
54+
if (cookie.getName().equalsIgnoreCase(name)) {
55+
return cookie.getValue();
56+
}
57+
}
58+
return null;
59+
60+
}
61+
62+
private MyHttpClient() {
63+
64+
}
65+
66+
/**
67+
* 获取cookies
68+
*
69+
* @author https://github.com/yaphone
70+
* @date 2017年5月7日 下午8:37:17
71+
* @return
72+
*/
73+
public static MyHttpClient getInstance() {
74+
if (instance == null) {
75+
synchronized (MyHttpClient.class) {
76+
if (instance == null) {
77+
instance = new MyHttpClient();
78+
}
79+
}
80+
}
81+
return instance;
3982
}
4083

4184
/**
@@ -108,4 +151,33 @@ public HttpEntity doPost(String url, String paramsStr) {
108151

109152
return entity;
110153
}
154+
155+
/**
156+
* 上传文件到服务器
157+
*
158+
* @author https://github.com/yaphone
159+
* @date 2017年5月7日 下午9:19:23
160+
* @param url
161+
* @param reqEntity
162+
* @return
163+
*/
164+
public HttpEntity doPostFile(String url, HttpEntity reqEntity) {
165+
HttpEntity entity = null;
166+
HttpPost httpPost = new HttpPost(url);
167+
httpPost.setHeader("User-Agent", Config.USER_AGENT);
168+
httpPost.setEntity(reqEntity);
169+
try {
170+
CloseableHttpResponse response = httpClient.execute(httpPost);
171+
entity = response.getEntity();
172+
173+
} catch (Exception e) {
174+
logger.info(e.getMessage());
175+
}
176+
return entity;
177+
}
178+
179+
public static CloseableHttpClient getHttpClient() {
180+
return httpClient;
181+
}
182+
111183
}

src/test/java/cn/zhouyafeng/itchat4j/demo/SimpleDemo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.alibaba.fastjson.JSONObject;
88

99
import cn.zhouyafeng.itchat4j.Wechat;
10+
import cn.zhouyafeng.itchat4j.api.MessageTools;
1011
import cn.zhouyafeng.itchat4j.face.IMsgHandlerFace;
1112
import cn.zhouyafeng.itchat4j.utils.DownloadTools;
1213
import cn.zhouyafeng.itchat4j.utils.MsgType;
@@ -23,6 +24,9 @@ public class SimpleDemo implements IMsgHandlerFace {
2324

2425
@Override
2526
public String textMsgHandle(JSONObject msg) {
27+
String filePath = "D:/itchat4j/pic/test.jpg";
28+
String userId = msg.getString("FromUserName");
29+
MessageTools.sendPicMsgByUserId(userId, filePath);
2630
String text = msg.getString("Text");
2731
return text;
2832
}

0 commit comments

Comments
 (0)