微信素材管理和群发这块文档对Java很不友好。本文只对新增临时素材,新增永久素材做介绍,其余获取、删除、修改自行补充
公众号经常有需要用到一些临时性的多媒体素材的场景,例如在使用接口特别是发送消息时,对多媒体文件、多媒体消息的获取和调用等操作,是通过media_id来进行的。素材管理接口对所有认证的订阅号和服务号开放。
素材的限制
图片(image): 2M,支持PNG\JPEG\JPG\GIF格式
语音(voice):2M,播放长度不超过60s,支持AMR\MP3格式
视频(video):10MB,支持MP4格式
缩略图(thumb):64KB,支持JPG格式
一、新增临时素材
接口:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE,再传一个媒体文件类型,可以是图片(image)、语音(voice)、视频(video)和缩略图(thumb)。
1、订阅号和服务号要通过认证
2、临时素材media_id是可复用的
3、媒体文件在微信后台保存时间为3天,即3天后media_id失效。
/** * 上传临时素材(本地) * * @param accessToken * @param type * 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) * @param path * 图片路径 * @return */ public static UploadMediasResult uploadTempMediaFile(String accessToken, String type, String path) { UploadMediasResult result = null; TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", type); try { String json = HttpsUploadMediaFile(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_TEMP_MEDIA_TYPE_URL, params, path); result = JsonUtil.fromJsonString(json, UploadMediasResult.class); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 上传临时素材(网络) * * @param accessToken * @param type * 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) * @param path * 图片路径 * @return */ public static UploadMediasResult uploadTempMedia(String accessToken, String type, String path) { UploadMediasResult result = null; TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", type); try { String json = HttpsUploadMedia(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_TEMP_MEDIA_TYPE_URL, params, path, 0, 0); result = JsonUtil.fromJsonString(json, UploadMediasResult.class); } catch (Exception e) { e.printStackTrace(); } return result; }
二、新增永久素材
接口:https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE,媒体文件类型,分别有图片(image)、语音(voice)、视频(video,例外)和缩略图(thumb)
/** * 上传永久素材(本地) * * @param accessToken * @param type * 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) * @return */ public static UploadMediasResult uploadForeverMediaFile(String accessToken, String type, String path) { UploadMediasResult result = null; TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", type); try { String json = HttpsUploadMediaFile(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_FOREVER_MEDIA_TYPE_URL, params, path); result = JsonUtil.fromJsonString(json, UploadMediasResult.class); } catch (Exception e) { e.printStackTrace(); } return result; } /** * 上传永久素材(网络) * * @param accessToken * @param type * 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) * @return */ public static UploadMediasResult uploadForeverMedia(String accessToken, String type, String path) { UploadMediasResult result = null; TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", type); try { String json = HttpsUploadMedia(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_FOREVER_MEDIA_TYPE_URL, params, path, 0, 0); result = JsonUtil.fromJsonString(json, UploadMediasResult.class); } catch (Exception e) { e.printStackTrace(); } return result; }
新增永久视频素材需特别注意,在上传视频素材时需要POST另一个表单,id为description,包含素材的描述信息title和introduction,内容格式为JSON
/** * 上传永久素材(video) * * @param accessToken * @return */ public static String uploadForeverMediaFile(String accessToken, String title, String introduction, String path) { TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", "video"); String mediaId = null; try { String json = HttpsUploadVideoMediaFile(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_FOREVER_MEDIA_TYPE_URL, params, path, title, introduction); mediaId = JsonUtil.fromJsonString(json, "media_id"); } catch (Exception e) { e.printStackTrace(); } return mediaId; } /** * 上传永久素材(video,网络) * * @param accessToken * @return */ public static String uploadForeverMedia(String accessToken, String title, String introduction, String path) { TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); params.put("type", "video"); String mediaId = null; try { String json = HttpsUploadVideoMedia(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_FOREVER_MEDIA_TYPE_URL, params, path, title, introduction, 0, 0); mediaId = JsonUtil.fromJsonString(json, "media_id"); } catch (Exception e) { e.printStackTrace(); } return mediaId; }
三、新增永久图文素材
接口:https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN,post信息参见UploadNewsMedia 实体类
对于常用的素材,开发者可通过本接口上传到微信服务器,永久使用.
1、永久图片素材新增后,将带有URL返回给开发者,开发者可以在腾讯系域名内使用(腾讯系域名外使用,图片将被屏蔽)。
2、公众号的素材库保存总数量有上限:图文消息素材、图片素材上限为5000,其他类型为1000。
3、图文消息的具体内容中,微信后台将过滤外部的图片链接,图片url需通过"上传图文消息内的图片获取URL"接口上传图片获取。
4、"上传图文消息内的图片获取URL"接口所上传的图片,不占用公众号的素材库中图片数量的5000个的限制,图片仅支持jpg/png格式,大小必须在1MB以下。
5、图文消息支持正文中插入自己帐号和其他公众号已群发文章链接的能力。
/** * 上传永久图文消息的素材 * * @param accessToken * 授权token * @param entity * 图文消息对象 * @return */ public static UploadMediasResult uploadNewsMedia(String accessToken, List<UploadNewsMedia> entity) { UploadMediasResult result = null; TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); // post 提交的参数 TreeMap<String, List<UploadNewsMedia>> dataParams = new TreeMap<String, List<UploadNewsMedia>>(); dataParams.put("articles", entity); String data = JsonUtil.toJsonString(dataParams); String json = HttpReqUtil.HttpsDefaultExecute(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_FOREVER_NEWS_MEDIA_URL, params, data); result = JsonUtil.fromJsonString(json, UploadMediasResult.class); return result; }
四、上传图文消息内的图片获取URL
接口:https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN
本接口所上传的图片不占用公众号的素材库中图片数量的5000个的限制。图片仅支持jpg/png格式,大小必须在1MB以下,此接口返回的url就是上传图片的URL,可放置图文消息中使用。
/** * 上传图文消息内的图片获取URL(本地) * * @param accessToken * @param path * @return */ public static String uploadImgMediaFile(String accessToken, String path) { TreeMap<String, String> params = new TreeMap<>(); params.put("access_token", accessToken); String url = null; try { String json = HttpsUploadMediaFile(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_IMG_MEDIA_URL, params, path); url = JsonUtil.fromJsonString(json, "url"); } catch (Exception e) { e.printStackTrace(); } return url; } /** * 上传图文消息内的图片获取URL(网络) * * @param accessToken * @param path * @return */ public static String uploadImgMedia(String accessToken, String path) { TreeMap<String, String> params = new TreeMap<String, String>(); params.put("access_token", accessToken); String url = null; try { String json = HttpsUploadMedia(SystemConfig.POST_METHOD, WechatConfig.UPLOAD_IMG_MEDIA_URL, params, path, 0, 0); url = JsonUtil.fromJsonString(json, "url"); } catch (Exception e) { e.printStackTrace(); } return url; }
五、部分工具类
配置类
public static final String UPLOAD_IMG_MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/media/uploadimg"; public static final String UPLOAD_FOREVER_NEWS_MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/material/add_news"; public static final String UPLOAD_TEMP_MEDIA_TYPE_URL = "https://api.weixin.qq.com/cgi-bin/media/upload"; public static final String UPLOAD_FOREVER_MEDIA_TYPE_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material";
上传图文消息素材返回类
package com.phil.wechat.msg.model.media; /** * 上传图文消息素材返回的结果 * @author phil * @date 2017年9月20日 * */ public class UploadMediasResult { private String type; // 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb),次数为news,即图文消息 private String media_id; // 媒体文件/图文消息上传后获取的唯一标识 private String created_at; // 媒体文件上传时间 }
上传图文消息素材实体类
package com.phil.wechat.msg.model.media; import java.io.Serializable; /** * 上传图文消息素材实体类 * @author phil * @date 2017年9月20日 */ public class UploadNewsMedia implements Serializable { private static final long serialVersionUID = 6551817058101753854L; private String thumb_media_id; // 图文消息缩略图的media_id,可以在基础支持-上传多媒体文件接口中获得 private String author; // 图文消息的作者 private String title; // 图文消息的标题 private String content_source_url; // 图文消息点击阅读原文的链接 private String content; // 图文消息页面的内容,支持HTML标签 private String digest; // 图文消息的描述 private int show_conver_pic; // 是否显示为封面 1表示显示为封面 0 不显示为封面 }
上传方法
/** * 上传媒体文件(本地) * * @param method * 请求方法 GET/POST * @param path * api的路径 * @param param * api参数 * @param mediaPath * 待上传的image/music 的path * @return * @throws Exception */ public static String HttpsUploadMediaFile(String method, String path, Map<String, String> param, String mediaPath) throws Exception { String result = null; URL url = new URL(setParmas(param, path, "")); OutputStream output = null; DataInputStream inputStream = null; try { File file = new File(mediaPath); if (!file.isFile() || !file.exists()) { throw new IOException("file is not exist"); } HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); con.setRequestMethod(SystemConfig.POST_METHOD); // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", SystemConfig.DEFAULT_CHARACTER_ENCODING); // 设置边界 String boundary = "----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); // 请求正文信息 // 第一部分 output = new DataOutputStream(con.getOutputStream()); IOUtils.write(("--" + boundary + "\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("Content-Disposition: form-data;name=\"media\"; filename=\"" + file.getName() + "\"\r\n") .getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write( "Content-Type:application/octet-stream\r\n\r\n".getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); // IOUtils.write(("Content-Type: "+ fileExt + "\r\n\r\n").getBytes(), output); // 文件正文部分 // 把文件已流文件的方式 推入到url中 inputStream = new DataInputStream(new FileInputStream(file)); IOUtils.copy(inputStream, output); // 结尾部分 IOUtils.write(("\r\n--" + boundary + "--\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); output.flush(); result = inputStreamToString(con.getInputStream()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { throw new IOException("read data error"); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(inputStream); } return result; } /** * 上传媒体文件(不能本地) * * @param method * 请求方法 GET/POST * @param path * api的路径 * @param param * api参数 * @param mediaPath * 待上传的image/music 的path * @param connTime * 连接时间 默认为5000 * @param readTime * 读取时间 默认为5000 * @return * @throws Exception */ public static String HttpsUploadMedia(String method, String path, Map<String, String> param, String mediaPath, int connTime, int readTime) throws Exception { String result = ""; URL url = new URL(setParmas(param, path, "")); OutputStream output = null; BufferedInputStream inputStream = null; try { String boundary = "----"; HttpURLConnection conn = getConnection(method, url); conn.setConnectTimeout(connTime == 0 ? DEFAULT_CONNTIME : connTime); conn.setReadTimeout(readTime == 0 ? DEFAULT_UPLOAD_READTIME : readTime); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); output = conn.getOutputStream(); URL mediaUrl = new URL(mediaPath); if (mediaUrl != null) { HttpURLConnection mediaConn = (HttpURLConnection) mediaUrl.openConnection(); mediaConn.setDoOutput(true); mediaConn.setUseCaches(false); mediaConn.setRequestMethod(SystemConfig.GET_METHOD); mediaConn.setConnectTimeout(connTime == 0 ? DEFAULT_CONNTIME : connTime); mediaConn.setReadTimeout(readTime == 0 ? DEFAULT_UPLOAD_READTIME : readTime); String connType = mediaConn.getContentType(); // 获得文件扩展 String fileExt = getFileExt(connType); IOUtils.write(("--" + boundary + "\r\n").getBytes(), output); IOUtils.write(("Content-Disposition: form-data; name=\"media\"; filename=\"" + getFileName(mediaPath) + "\"\r\n").getBytes(), output); IOUtils.write(("Content-Type: " + fileExt + "\r\n\r\n").getBytes(), output); inputStream = new BufferedInputStream(mediaConn.getInputStream()); IOUtils.copy(inputStream, output); IOUtils.write(("\r\n----" + boundary + "--\r\n").getBytes(), output); mediaConn.disconnect(); // 获取输入流 result = inputStreamToString(conn.getInputStream()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(inputStream); } return result; } /** * 上传Video媒体文件(本地) * * @param method * 请求方法 GET/POST * @param path * api的路径 * @param param * api参数 * @param mediaPath * 待上传的voide 的path * @param title * 视频标题 * @param introduction * 视频描述 * @return * @throws Exception */ public static String HttpsUploadVideoMediaFile(String method, String path, Map<String, String> param, String mediaPath, String title, String introduction) throws Exception { String result = null; URL url = new URL(setParmas(param, path, "")); OutputStream output = null; DataInputStream inputStream = null; try { File file = new File(mediaPath); if (!file.isFile() || !file.exists()) { throw new IOException("file is not exist"); } HttpURLConnection con = (HttpURLConnection) url.openConnection(); con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); con.setRequestMethod(SystemConfig.POST_METHOD); // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", SystemConfig.DEFAULT_CHARACTER_ENCODING); // 设置边界 String boundary = "----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary); // 请求正文信息 // 第一部分 output = new DataOutputStream(con.getOutputStream()); IOUtils.write(("--" + boundary + "\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("Content-Disposition: form-data;name=\"media\"; filename=\"" + file.getName() + "\"\r\n") .getBytes(), output); IOUtils.write("Content-Type: video/mp4 \r\n\r\n".getBytes(), output); // 文件正文部分 // 把文件已流文件的方式 推入到url中 inputStream = new DataInputStream(new FileInputStream(file)); IOUtils.copy(inputStream, output); // 结尾部分 IOUtils.write(("--" + boundary + "\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write("Content-Disposition: form-data; name=\"description\";\r\n\r\n" .getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("{\"title\":\"" + title + "\",\"introduction\":\"" + introduction + "\"}") .getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("\r\n--" + boundary + "--\r\n\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); output.flush(); result = inputStreamToString(con.getInputStream()); } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { throw new IOException("read data error"); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(inputStream); } return result; } /** * 上传Video媒体文件(网络) * * @param method * 请求方法 GET/POST * @param path * api的路径 * @param param * api参数 * @param mediaPath * 待上传的voide 的path * @param title * 视频标题 * @param introduction * 视频描述 * @param connTime * 连接时间 默认为5000 * @param readTime * 读取时间 默认为5000 * @return * @throws Exception */ public static String HttpsUploadVideoMedia(String method, String path, Map<String, String> param, String mediaPath, String title, String introduction, int connTime, int readTime) throws Exception { String result = null; URL url = new URL(setParmas(param, path, "")); OutputStream output = null; BufferedInputStream inputStream = null; try { String boundary = "----"; HttpURLConnection conn = getConnection(method, url); conn.setConnectTimeout(connTime == 0 ? DEFAULT_CONNTIME : connTime); conn.setReadTimeout(readTime == 0 ? DEFAULT_UPLOAD_READTIME : readTime); conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); output = conn.getOutputStream(); URL mediaUrl = new URL(mediaPath); if (mediaUrl != null) { HttpURLConnection mediaConn = (HttpURLConnection) mediaUrl.openConnection(); mediaConn.setDoOutput(true); mediaConn.setUseCaches(false); mediaConn.setRequestMethod(SystemConfig.GET_METHOD); mediaConn.setConnectTimeout(connTime == 0 ? DEFAULT_CONNTIME : connTime); mediaConn.setReadTimeout(readTime == 0 ? DEFAULT_UPLOAD_READTIME : readTime); IOUtils.write(("--" + boundary + "\r\n").getBytes(), output); IOUtils.write(("Content-Disposition: form-data; name=\"media\"; filename=\"" + getFileName(mediaPath) + "\"\r\n").getBytes(), output); IOUtils.write("Content-Type: video/mp4 \r\n\r\n".getBytes(), output); inputStream = new BufferedInputStream(mediaConn.getInputStream()); IOUtils.copy(inputStream, output); // 结尾部分 IOUtils.write(("--" + boundary + "\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write("Content-Disposition: form-data; name=\"description\";\r\n\r\n" .getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("{\"title\":\"" + title + "\",\"introduction\":\"" + introduction + "\"}") .getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); IOUtils.write(("\r\n--" + boundary + "--\r\n\r\n").getBytes(SystemConfig.DEFAULT_CHARACTER_ENCODING), output); mediaConn.disconnect(); // 获取输入流 result = inputStreamToString(conn.getInputStream()); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (ProtocolException e) { e.printStackTrace(); } catch (IOException e) { throw new IOException("read data error"); } finally { IOUtils.closeQuietly(output); IOUtils.closeQuietly(inputStream); } return result; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持小牛知识库。
本文向大家介绍Java微信公众平台开发(1) 接入微信公众平台,包括了Java微信公众平台开发(1) 接入微信公众平台的使用技巧和注意事项,需要的朋友参考一下 前面几篇文章一直都在说微信公众平台的开发准备工作,那么从这篇开始我们就将正式的进入JAVA微信公众平台开发的整个流程,那么这篇我们开始聊聊如何将我们的服务端和微信公众平台对接! (一)接入流程解析 在我们的开发过程中无论如何最好的参考工具当
本文向大家介绍Java微信公众平台之自定义菜单,包括了Java微信公众平台之自定义菜单的使用技巧和注意事项,需要的朋友参考一下 一、自定义菜单的说明和按钮类型 1、菜单说明 1)自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。 2)一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。 3)创建自定义菜单后,菜单的刷新策略是,在用户进入公众号会话页或公众号
本文向大家介绍Java微信公众平台之获取地理位置,包括了Java微信公众平台之获取地理位置的使用技巧和注意事项,需要的朋友参考一下 本部分需要用到微信的JS-SDK,微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能
本文向大家介绍Java微信公众平台之群发接口(高级群发),包括了Java微信公众平台之群发接口(高级群发)的使用技巧和注意事项,需要的朋友参考一下 再次吐槽下,微信素材管理和群发这块文档对Java很不友好,此文需要结合我前文和官方文档。 测试号调试群发只需看是否群发消息是否能组装成功,不需要看结果如何(反正不会发送成功的),因为微信还没开放这个功能(估计也不会开放的)。 一、群发说明 在公众平台网
本文向大家介绍微信公众平台开发之配置与请求,包括了微信公众平台开发之配置与请求的使用技巧和注意事项,需要的朋友参考一下 一、配置参数 1)微信公众号开发中ID WEIXIN_APPID: 应用ID WEIXIN_APPSECRET: 应用密钥 进入到公众平台首页,点击开发者中心,赫然就能看到,配置页面中的,这两个默认就是有的。 2)服务器配置 WEIXIN_TOKEN,也就是token令牌,自定义
本文向大家介绍详解nodejs微信公众号开发——5.素材管理接口,包括了详解nodejs微信公众号开发——5.素材管理接口的使用技巧和注意事项,需要的朋友参考一下 上一篇文章:nodejs微信公众号开发——4.自动回复各种消息,我们实现了被动回复文字和图文,回复图片失败,因为需要先获取通过素材管理接口上传多媒体文件而得到的MediaId,这一节们就来实现素材管理的接口。可参看:公众平台开发者文档