Java企业微信开发_07_素材管理之上传本地临时素材文件
Posted shirayner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java企业微信开发_07_素材管理之上传本地临时素材文件相关的知识,希望对你有一定的参考价值。
一、本节要点
1.临时素材有效期
media_id是可复用的,同一个media_id可用于消息的多次发送(3天内有效)
2.上传文件时的http请求里都有啥
具体原理可参看: 为什么上传文件的表单需要设置enctype="multipart/form-data" (http://blog.csdn.net/mazhibinit/article/details/49667511)
3.上传本地临时素材到微信服务器的流程
(1)建立与微信服务器的网络连接
(2)从连接中获取输出流(写入微信服务器的),将本地文件以文件流的形式 写入输出流
(3)从连接中获取输入流(微信服务器返回的),获取输入流中的微信服务器返回的数据(type、media_id、created_at)
(4)上传完素材就要使用素材了:这时,我们拿着上一步的media_id,去做发送图片消息的测试。
二、代码实现
1. 微信上传素材的请求方法
public static String httpRequest(String requestUrl, File file)
/** * @desc :微信上传素材的请求方法 * * @param requestUrl 微信上传临时素材的接口url * @param file 要上传的文件 * @return String 上传成功后,微信服务器返回的消息 */ public static String httpRequest(String requestUrl, File file) { StringBuffer buffer = new StringBuffer(); try{ //1.建立连接 URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); //打开链接 //1.1输入输出设置 httpUrlConn.setDoInput(true); httpUrlConn.setDoOutput(true); httpUrlConn.setUseCaches(false); // post方式不能使用缓存 //1.2设置请求头信息 httpUrlConn.setRequestProperty("Connection", "Keep-Alive"); httpUrlConn.setRequestProperty("Charset", "UTF-8"); //1.3设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY); // 请求正文信息 // 第一部分: //2.将文件头输出到微信服务器 StringBuilder sb = new StringBuilder(); sb.append("--"); // 必须多两道线 sb.append(BOUNDARY); sb.append("\\r\\n"); sb.append("Content-Disposition: form-data;name=\\"media\\";filelength=\\"" + file.length() + "\\";filename=\\""+ file.getName() + "\\"\\r\\n"); sb.append("Content-Type:application/octet-stream\\r\\n\\r\\n"); byte[] head = sb.toString().getBytes("utf-8"); // 获得输出流 OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream()); // 将表头写入输出流中:输出表头 outputStream.write(head); //3.将文件正文部分输出到微信服务器 // 把文件以流文件的方式 写入到微信服务器中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { outputStream.write(bufferOut, 0, bytes); } in.close(); //4.将结尾部分输出到微信服务器 byte[] foot = ("\\r\\n--" + BOUNDARY + "--\\r\\n").getBytes("utf-8");// 定义最后数据分隔线 outputStream.write(foot); outputStream.flush(); outputStream.close(); //5.将微信服务器返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); } catch (IOException e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } return buffer.toString(); }
2.微信工具类——WeiXinUtil
我们将1中的微信上传素材的请求方法封装到WeiXinUtil.ava中
package com.ray.util; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.net.ConnectException; import java.net.HttpURLConnection; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Formatter; import java.util.HashMap; import java.util.Map; import java.util.UUID; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.servlet.http.HttpServletRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.ray.pojo.AccessToken; import net.sf.json.JSONException; import net.sf.json.JSONObject; public class WeiXinUtil { private static Logger log = LoggerFactory.getLogger(WeiXinUtil.class); //微信的请求url //获取access_token的接口地址(GET) 限200(次/天) public final static String access_token_url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={corpId}&corpsecret={corpsecret}"; /** * 1.发起https请求并获取结果 * * @param requestUrl 请求地址 * @param requestMethod 请求方式(GET、POST) * @param outputStr 提交的数据 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值) */ public static JSONObject httpRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject = null; StringBuffer buffer = new StringBuffer(); try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = { new MyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection httpUrlConn = (HttpsURLConnection) url.openConnection(); httpUrlConn.setSSLSocketFactory(ssf); httpUrlConn.setDoOutput(true); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); // 设置请求方式(GET/POST) httpUrlConn.setRequestMethod(requestMethod); if ("GET".equalsIgnoreCase(requestMethod)) httpUrlConn.connect(); // 当有数据需要提交时 if (null != outputStr) { OutputStream outputStream = httpUrlConn.getOutputStream(); // 注意编码格式,防止中文乱码 outputStream.write(outputStr.getBytes("UTF-8")); outputStream.close(); } // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); jsonObject = JSONObject.fromObject(buffer.toString()); } catch (ConnectException ce) { log.error("Weixin server connection timed out."); } catch (Exception e) { log.error("https request error:{}", e); } return jsonObject; } /** * @desc :微信上传素材的请求方法 * * @param requestUrl 微信上传临时素材的接口url * @param file 要上传的文件 * @return String 上传成功后,微信服务器返回的消息 */ public static String httpRequest(String requestUrl, File file) { StringBuffer buffer = new StringBuffer(); try{ //1.建立连接 URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); //打开链接 //1.1输入输出设置 httpUrlConn.setDoInput(true); httpUrlConn.setDoOutput(true); httpUrlConn.setUseCaches(false); // post方式不能使用缓存 //1.2设置请求头信息 httpUrlConn.setRequestProperty("Connection", "Keep-Alive"); httpUrlConn.setRequestProperty("Charset", "UTF-8"); //1.3设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); httpUrlConn.setRequestProperty("Content-Type","multipart/form-data; boundary="+ BOUNDARY); // 请求正文信息 // 第一部分: //2.将文件头输出到微信服务器 StringBuilder sb = new StringBuilder(); sb.append("--"); // 必须多两道线 sb.append(BOUNDARY); sb.append("\\r\\n"); sb.append("Content-Disposition: form-data;name=\\"media\\";filelength=\\"" + file.length() + "\\";filename=\\""+ file.getName() + "\\"\\r\\n"); sb.append("Content-Type:application/octet-stream\\r\\n\\r\\n"); byte[] head = sb.toString().getBytes("utf-8"); // 获得输出流 OutputStream outputStream = new DataOutputStream(httpUrlConn.getOutputStream()); // 将表头写入输出流中:输出表头 outputStream.write(head); //3.将文件正文部分输出到微信服务器 // 把文件以流文件的方式 写入到微信服务器中 DataInputStream in = new DataInputStream(new FileInputStream(file)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { outputStream.write(bufferOut, 0, bytes); } in.close(); //4.将结尾部分输出到微信服务器 byte[] foot = ("\\r\\n--" + BOUNDARY + "--\\r\\n").getBytes("utf-8");// 定义最后数据分隔线 outputStream.write(foot); outputStream.flush(); outputStream.close(); //5.将微信服务器返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); } catch (IOException e) { System.out.println("发送POST请求出现异常!" + e); e.printStackTrace(); } return buffer.toString(); } /** * 2.发起http请求获取返回结果 * * @param requestUrl 请求地址 * @return */ public static String httpRequest(String requestUrl) { StringBuffer buffer = new StringBuffer(); try { URL url = new URL(requestUrl); HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection(); httpUrlConn.setDoOutput(false); httpUrlConn.setDoInput(true); httpUrlConn.setUseCaches(false); httpUrlConn.setRequestMethod("GET"); httpUrlConn.connect(); // 将返回的输入流转换成字符串 InputStream inputStream = httpUrlConn.getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8"); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String str = null; while ((str = bufferedReader.readLine()) != null) { buffer.append(str); } bufferedReader.close(); inputStreamReader.close(); // 释放资源 inputStream.close(); inputStream = null; httpUrlConn.disconnect(); } catch (Exception e) { } return buffer.toString(); } /** * 3.获取access_token * * @param appid 凭证 * @param appsecret 密钥 * @return */ public static AccessToken getAccessToken(String appid, String appsecret) { AccessToken accessToken = null; String requestUrl = access_token_url.replace("{corpId}", appid).replace("{corpsecret}", appsecret); JSONObject jsonObject = httpRequest(requestUrl, "GET", null); // 如果请求成功 if (null != jsonObject) { try { accessToken = new AccessToken(); accessToken.setToken(jsonObject.getString("access_token")); accessToken.setExpiresIn(jsonObject.getInt("expires_in")); } catch (JSONException e) { accessToken = null; // 获取token失败 log.error("获取token失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg")); } } return accessToken; } /** * 3.获取微信的JSSDK配置信息 * 方法名:getWxConfig</br> * 详述:获取微信的配置信息 </br> * 开发人员:souvc </br> * 创建时间:2016-1-5 </br> * @param request * @return 说明返回值含义 * @throws 说明发生此异常的条件 */ public static Map<String, Object> getWxConfig(HttpServletRequest request) { Map<String, Object> ret = new HashMap<String, Object>(); String appId = "wxa0064ea657f80062"; // 必填,公众号的唯一标识 String secret = "fcc960840df869ad1a46af7993784917"; String requestUrl = request.getRequestURL().toString(); String access_token = ""; String jsapi_ticket = ""; String timestamp = Long.toString(System.currentTimeMillis() / 1000); // 必填,生成签名的时间戳 String nonceStr = UUID.randomUUID().toString(); // 必填,生成签名的随机串 String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+ appId + "&secret=" + secret; //使用http请求获取access_token JSONObject json = WeiXinUtil.httpRequest(url, "GET", null); System.out.println(" 获取access_token "+json); if (json != null) { //要注意,access_token需要缓存 access_token = json.getString("access_token"); //根据access_token获取jsapi_ticket url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token + "&type=jsapi"; json = WeiXinUtil.httpRequest(url, "GET", null); System.out.println("jsapi_ticket "+json); if (json != null) { jsapi_ticket = json.getString("ticket"); } } String signature = ""; // 注意这里参数名必须全部小写,且必须有序 String sign = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr+ "×tamp=" + timestamp + "&url=" + requestUrl; try { MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(sign.getBytes("UTF-8")); signature = byteToHex(crypt.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } ret.put("appId", appId); ret.put("timestamp", timestamp); ret.put("nonceStr", nonceStr); ret.put("signature", signature); return ret; } /** * 方法名:byteToHex</br> * 详述:字符串加密辅助方法 </br> * 开发人员:souvc </br> * 创建时间:2016-1-5 </br> * @param hash * @return 说明返回值含义 * @throws 说明发生此异常的条件 */ private static String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; } }
3.业务类——TempMaterialService
package com.ray.service; import java.io.File; import com.ray.util.WeiXinUtil; import net.sf.json.JSONObject; /**@desc : 临时素材业务类 * * @author: shirayner * @date : 2017-8-18 下午2:07:25 */ public class TempMaterialService { //上传临时素材url public static String uploadTempMaterial_url="https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE"; /** * @desc :上传临时素材 * * @param accessToken 接口访问凭证 * @param type 媒体文件类型,分别有图片(image)、语音(voice)、视频(video),普通文件(file) * @param fileUrl 本地文件的url。例如 "D/1.img"。 * @return JSONObject 上传成功后,微信服务器返回的参数,有type、media_id 、created_at */ public JSONObject uploadTempMaterial(String accessToken,String type,String fileUrl){ //1.创建本地文件 File file=new File(fileUrl); //2.拼接请求url uploadTempMaterial_url=uploadTempMaterial_url.replace("ACCESS_TOKEN", accessToken) .replace("TYPE", type); //3.调用接口,发送请求,上传文件到微信服务器 String result=WeiXinUtil.httpRequest(uploadTempMaterial_url, file); //4.json字符串转对象:解析返回值,json反序列化 result = result.replaceAll("[\\\\\\\\]", ""); System.out.println("result:" + result); JSONObject resultJSON = JSONObject.fromObject(result); //5.返回参数判断 if (resultJSON != null) { if (resultJSON.get("media_id") != null) { System.out.println("上传" + type + "永久素材成功"); return resultJSON; } else { System.out.println("上传" + type + "永久素材失败"); } } return null; } }
4.测试类——TempMaterialTest
package com.ray.test; import org.junit.Test; import com.ray.service.TempMaterialService; import com.ray.util.WeiXinParamesUtil; import com.ray.util.WeiXinUtil; /**@desc : 临时素材 * * @author: shirayner * @date : 2017-8-18 下午2:06:10 */ public class TempMaterialTest { @Test public void testUploadTempMaterial(){ //1.初始化参数 String fileUrl="D:/renwu1.jpg"; String type="image"; String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.contactsSecret).getToken(); //2.调用业务类,上传临时素材 TempMaterialService tms=new TempMaterialService(); tms.uploadTempMaterial(accessToken, type, fileUrl); } }
这时在控制台上会打印出微信服务器返回的media_id,我们拿着这个media_id去完成发送消息之发送图片消息的测试,参见 Java企业微信开发_05_消息推送之发送消息(主动)
5.测试类——SendMessageTest
package com.ray.test; import java.util.ArrayList; import java.util.List; import org.junit.Test; import com.ray.pojo.message.send.Article; import com.ray.pojo.message.send.FileMessage; import com.ray.pojo.message.send.ImgMessage; import com.ray.pojo.message.send.Media; import com.ray.pojo.message.send.News; import com.ray.pojo.message.send.NewsMessage; import com.ray.pojo.message.send.Text; import com.ray.pojo.message.send.TextMessage; import com.ray.pojo.message.send.Textcard; import com.ray.pojo.message.send.TextcardMessage; import com.ray.pojo.message.send.Video; import com.ray.pojo.message.send.VideoMessage; import com.ray.pojo.message.send.VoiceMessage; import com.ray.service.SendMessageService; import com.ray.util.WeiXinParamesUtil; import com.ray.util.WeiXinUtil; /**@desc : 消息推送之发送消息 * * @author: shirayner * @date : 2017-8-18 上午10:04:55 */ public class SendMessageTest { //1.发送文本消息 @Test public void testSendTextMessage(){ //0.设置消息内容 String content="rayge,你好!你的快递已到,请携带工卡前往邮件中心领取。\\n出发前可查看" + "<a href=\\"http://work.weixin.qq.com\\">邮件中心视频实况" + "</a>,聪明避开排队。"; //1.创建文本消息对象 TextMessage message=new TextMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("text"); message.setAgentid(WeiXinParamesUtil.agentId); Text text=new Text(); text.setContent(content); message.setText(text); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //2.发送文本卡片消息 @Test public void testSendTextcardMessage(){ //0.设置消息内容 String title="代办事宜"; String description="<div class=\\"gray\\">2017年8月18日</div> <div class=\\"normal\\">" + "恭喜你抽中iPhone 7一台,领奖码:xxxx</div><div class=\\"highlight\\">" + "请于2017年10月10日前联系行政同事领取</div>"; String url="http://www.cnblogs.com/shirui/p/7297872.html"; //1.创建文本卡片消息对象 TextcardMessage message=new TextcardMessage(); //1.1非必需 message.setTouser("shirui"); //不区分大小写 //message.setToparty("1"); //message.setTotag(totag); //message.setSafe(0); //1.2必需 message.setMsgtype("textcard"); message.setAgentid(WeiXinParamesUtil.agentId); Textcard textcard=new Textcard(); textcard.setTitle(title); textcard.setDescription(description); textcard.setUrl(url); message.setTextcard(textcard); //2.获取access_token:根据企业id和通讯录密钥获取access_token,并拼接请求url String accessToken= WeiXinUtil.getAccessToken(WeiXinParamesUtil.corpId, WeiXinParamesUtil.agentSecret).getToken(); System.out.println("accessToken:"+accessToken); //3.发送消息:调用业务类,发送消息 SendMessageService sms=new SendMessageService(); sms.sendMessage(accessToken, message); } //3.发送图片消息---无效的media_id @Test public void testSendImgMessage(){ //0.设置消息内容 //String media_id="MEDIA_ID"; String media_id="3oKgxI6C_Z_8gPr5a1ORIhYTLlMJnoMWbrRIrip2p6oQ"; //1.创建图片消息对象 ImgMessage message=new ImgMessage(); //1.1非必需 message.setTouser("@all"); //不区分大小写 //textMessage.setToparty("1"); //txtMsg.setTotag(totag); //txtMsg.setSafe(0); //1.2必需 message.setMsgtype("image"); message.setAgentid(WeiXinParamesUtil.agentId); Media image以上是关于Java企业微信开发_07_素材管理之上传本地临时素材文件的主要内容,如果未能解决你的问题,请参考以下文章