第六篇:微信素材管理工具類
阿新 • • 發佈:2018-11-13
1、前言
微信公眾號在使用的介面的時候是通過media_id來進行的,所以在使用的介面的時候我們往往需要先上傳素材,素材管理分為臨時素材和永久素材
1)、臨時素材媒體檔案在微信後臺儲存時間為3天,即3天后media_id失效,詳細文件檢視:上傳臨時素材
2)、開發者可通過本介面上傳到微信伺服器,永久使用。新增的永久素材也可以在公眾平臺官網素材管理模組中查詢管理。
除了可以上傳以上提到的4種素材外,還可以上傳圖文素材。
以下是一些說明:
a. 公眾號的素材庫儲存總數量有上限:圖文訊息素材、圖片素材上限為5000,其他型別為1000。
b. 圖文訊息的具體內容中,微信後臺將過濾外部的圖片連結,圖片url需通過"上傳圖文訊息內的圖片獲取URL"介面上傳圖片獲取。
c.
d. 圖文訊息支援正文中插入自己帳號和其他公眾號已群發文章連結的能力。
3)、支援上傳素材的格式和限制如下
圖片(image): 2M,支援PNG\JPEG\JPG\GIF格式。
語音(voice):2M,播放長度不超過60s,支援AMR\MP3格式。
視訊(video):10MB,支援MP4格式。
縮圖(thumb):64KB,支援JPG格式。
2、微信框架
開源框架使用weixin-java-mp, 微信框架 參考:https://github.com/Wechat-Group/weixin-java-tools
3、微信素材管理工具類
package com.thinkgem.jeesite.modules.wechat.commonUtil; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.UUID; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.api.WxConsts; import me.chanjar.weixin.common.bean.result.WxMediaUploadResult; import me.chanjar.weixin.common.exception.WxErrorException; import me.chanjar.weixin.common.util.fs.FileUtils; import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.bean.WxMpMassNews; import me.chanjar.weixin.mp.bean.WxMpMassOpenIdsMessage; import me.chanjar.weixin.mp.bean.WxMpMassTagMessage; import me.chanjar.weixin.mp.bean.material.WxMediaImgUploadResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterial; import me.chanjar.weixin.mp.bean.material.WxMpMaterialArticleUpdate; import me.chanjar.weixin.mp.bean.material.WxMpMaterialCountResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialFileBatchGetResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNewsBatchGetResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialVideoInfoResult; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNews.WxMpMaterialNewsArticle; import me.chanjar.weixin.mp.bean.material.WxMpMaterialNewsBatchGetResult.WxMaterialNewsBatchGetNewsItem; import me.chanjar.weixin.mp.bean.material.WxMpMaterialUploadResult; import me.chanjar.weixin.mp.bean.result.WxMpMassUploadResult; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Maps; /** * <pre> * 微信素材管理 <br /> * 注 : 封面圖需要用永久、富文字中圖片永久和臨時都可以、群發圖文如果臨時用下就用臨時素材,否則用永久素材(大部分選永久) * @author cao_wencao * @date 2018年8月8日 * </pre> */ @Slf4j @Component public class WeChatUtils { @Autowired private WxMpService wxMpService; private static Map<String, Map<String, Object>> mediaIds = Maps.newLinkedHashMap(); /** * <pre> * 上傳群發用的圖文訊息,上傳後才能群發圖文訊息. * * @see #massGroupMessageSend(WxMpMassTagMessage) 按分組群發 * @see #massOpenIdsMessageSend(WxMpMassOpenIdsMessage) 按openid群發 * @author cao_wencao * @param news * @return * </pre> */ public WxMpMassUploadResult massNewsUpload(WxMpMassNews news) { // 圖文上傳 WxMpMassUploadResult massUploadResult = null; try { massUploadResult = wxMpService.getMassMessageService().massNewsUpload(news); if (null != massUploadResult) { log.info("\n【上傳圖文素材】成功: {}", massUploadResult.getMediaId()); return massUploadResult; } } catch (Exception e) { log.error("\n【上傳圖文素材】失敗 : {}", e.getMessage()); e.printStackTrace(); } return massUploadResult; } /** * <pre> * 上傳臨時多媒體檔案 * 比如圖文訊息的封面圖 圖片(image): 2M,支援PNG\JPEG\JPG\GIF格式 * 語音(voice):2M,播放長度不超過60s,支援AMR\MP3格式 視訊(video):10MB,支援MP4格式 * 縮圖(thumb):64KB,支援JPG格式 * * @author cao_wencao * @param mediaType * 媒體檔案型別,分別有圖片(image)、語音(voice)、視訊(video)和縮圖(thumb) * @param fileType * 檔案字尾 * * @param inputStream * 檔案輸入流 * @return type,media_id,created_at * </pre> */ public WxMediaUploadResult mediaUpload(String mediaType, String fileType, InputStream inputStream) { if (null == inputStream || null == mediaType || null == fileType) { return null; } WxMediaUploadResult res = null; try { res = this.wxMpService.getMaterialService().mediaUpload(mediaType, fileType, inputStream); log.info("\n【多媒體檔案上傳】成功MediaId : {} ", res.getMediaId()); return res; } catch (Exception e) { log.error("\n【多媒體檔案上傳】失敗 : {}", e.getMessage()); e.printStackTrace(); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return res; } /** * <pre> * 上傳圖文訊息內的圖片獲取URL(圖文訊息裡面的圖片) * * 請注意,本介面所上傳的圖片不佔用公眾號的素材庫中圖片數量的5000個的限制。圖片僅支援jpg/png格式,大小必須在1MB以下。 * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738729&token=&lang=zh_CN">新增永久素材</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN * </pre> * * @param file * 上傳的檔案物件 * @return WxMediaImgUploadResult 返回圖片url * */ public WxMediaImgUploadResult uploadimg(File file) { if (null == file) { return null; } WxMediaImgUploadResult imageUploadResult = null; try { imageUploadResult = this.wxMpService.getMaterialService().mediaImgUpload(file); log.info("\n【上傳圖文訊息內的圖片】成功 : {}", imageUploadResult.getUrl()); return imageUploadResult; } catch (Exception e) { log.error("\n【上傳圖文訊息內的圖片】失敗 : {}", e.getMessage()); e.printStackTrace(); } return imageUploadResult; } /** * <pre> * 獲取臨時素材 * 公眾號可以使用本介面獲取臨時素材(即下載臨時的多媒體檔案)。請注意,視訊檔案不支援https下載,呼叫該介面需http協議。 * 本介面即為原“下載多媒體檔案”介面。 * 根據微信文件,視訊檔案下載不了,會返回null * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738727&token=&lang=zh_CN">獲取臨時素材</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID * </pre> * * @param mediaId * 媒體檔案Id * @return 儲存到本地的臨時檔案 * @throws Exception */ public File DownloadMaterial(String mediaId) { if (null == mediaId) { return null; } File file = null; try { file = this.wxMpService.getMaterialService().mediaDownload(mediaId); return file; } catch (Exception e) { log.error("\n【下載臨時素材】失敗 : {}", e.getMessage()); e.printStackTrace(); } return file; } // =======================================永久素材 : // 下載、上傳、刪除、更新==================================================== /** * <pre> * 新增其他型別永久素材 非圖文永久素材上傳 * @author cao_wencao * @param mediaType * 媒體檔案型別 :分別有圖片(image)、語音(voice)、視訊(video)和縮圖(thumb) * images支援 :bmp/png/jpeg/jpg/gif格式 * @param fileType * @param fileName * @return WxMpMaterialUploadResult : "media_id":MEDIA_ID, "url":URL(永久素材型別為images才會返回url) * </pre> */ public WxMpMaterialUploadResult uploadFilesToWeChat(String mediaType, String fileType, String fileName, InputStream inputStream) { if (null == mediaType || null == fileType || null == inputStream || null == fileName) { return null; } WxMpMaterialUploadResult uploadResult = null; try { File tempFile = FileUtils.createTmpFile(inputStream, UUID.randomUUID().toString(), fileType); WxMpMaterial wxMaterial = new WxMpMaterial(); wxMaterial.setFile(tempFile); wxMaterial.setName(fileName); // 視訊類永久素材需要在構造時傳入視訊名title和簡介introduction,目前已知視訊支援mp4格式。 if (WxConsts.MediaFileType.VIDEO.equals(mediaType)) { wxMaterial.setVideoTitle("title"); wxMaterial.setVideoIntroduction("test video description"); } // 上傳素材至微信伺服器 uploadResult = wxMpService.getMaterialService().materialFileUpload(mediaType, wxMaterial); // 圖片才會有url,其他均是media_id if (null != uploadResult && !StringUtils.isBlank(uploadResult.getMediaId())) { log.info("\n【上傳素材mediaType】 : {},{}成功!", uploadResult.getUrl(), uploadResult.getMediaId()); return uploadResult; } } catch (Exception e) { log.error("\n【上傳素材mediaType】: {}失敗 ", e.getMessage()); e.printStackTrace(); } return uploadResult; } /** * <pre> * 新增永久圖文素材 * 方法名: uploadNewsToWeChat * 引數: WxMpMaterialNews * 返回值: * WxMpMaterialUploadResult 圖文素材支援單圖文和多圖文,由類 WxMpMaterialNews 進行封裝,圖文的資料通過類 * WxMpMaterialNews.WxMpMaterialNewsArticle 封裝。 多圖文訊息在 WxMpMaterialNews 中呼叫 * addArticle 方法新增多個 WxMpMaterialNewsArticle 物件即可。 介面返回 新增圖文訊息的media_id * * @author cao_wencao * @param materialNews * 要上傳的圖文訊息的素材 * @return String * </pre> */ public WxMpMaterialUploadResult uploadNewsToWeChat(WxMpMaterialNews materialNews) { String media_id = null; WxMpMaterialUploadResult uploadResult = null; try { uploadResult = wxMpService.getMaterialService().materialNewsUpload(materialNews); if (null != uploadResult && !StringUtils.isBlank(uploadResult.getMediaId())) { media_id = uploadResult.getMediaId(); log.info("\n【上傳圖文訊息】成功:{}", media_id); return uploadResult; } } catch (Exception e) { log.error("\n【上傳圖文素材】失敗 : {}", e.getMessage()); e.printStackTrace(); } return uploadResult; } /** * <pre> * 圖文永久素材下載 根據 media_id 獲取圖文訊息, * 結果由 WxMpMaterialNews 封裝,該類的結構和微信伺服器返回的 json, * 格式資料的結構保持一致。 * * @author cao_wencao * @param newsMediaId * 要下載的圖文訊息的id * @return WxMpMaterialNews * </pre> */ public WxMpMaterialNews newsInfoDownload(String newsMediaId) { WxMpMaterialNews wxMpMaterialNews = null; try { wxMpMaterialNews = wxMpService.getMaterialService().materialNewsInfo(newsMediaId); log.info("\n【下載圖文素材】成功 : {}", wxMpMaterialNews.toJson().toString()); return wxMpMaterialNews; } catch (Exception e) { log.error("\n【下載圖文素材】失敗 :{}", newsMediaId); e.printStackTrace(); } return wxMpMaterialNews; } /** * <pre> * 永久素材刪除 根據 media_id 刪除素材 * * @author cao_wencao * @param mediaId * 要刪除的圖文訊息的id * @return Boolean * </pre> */ public Boolean DeleteMaterial(String mediaId) { Boolean result = false; try { result = wxMpService.getMaterialService().materialDelete(mediaId); log.info("\n【刪除永久素材】成功 : {} ;/n返回值 : {} ", mediaId, result); return result; } catch (Exception e) { log.error("\n【刪除永久素材】失敗 : {} ;/n返回值 : {} ", mediaId, result); e.printStackTrace(); } return result; } /** * <pre> * 獲取圖文素材列表 並且下載 * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738734&token=&lang=zh_CN">獲取素材列表</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token=ACCESS_TOKEN * @param offset * 從全部素材的該偏移位置開始返回,0表示從第一個素材 返回 * @param count * 返回素材的數量,取值在1到20之間 * </pre> */ public WxMpMaterialNews materialNewsBatchGet(int offset, int count) throws Exception { if (offset < 0 || count <= 0) { return null; } WxMpMaterialNewsBatchGetResult newsBatchGetResult = null; WxMpMaterialNews wxMpMaterialNews = null; try { newsBatchGetResult = this.wxMpService.getMaterialService().materialNewsBatchGet(offset, count); if (newsBatchGetResult.getTotalCount() > 0 || newsBatchGetResult.getItemCount() > 0) { List<WxMaterialNewsBatchGetNewsItem> items = newsBatchGetResult.getItems(); for (int i = 0; i < items.size(); i++) { String mediaId = items.get(i).getMediaId(); if (StringUtils.isBlank(mediaId)) { log.debug("【獲取微信圖文素材mediaId】失敗!"); return null; } // 調取圖文素材下載介面 ,引數 :mediaId wxMpMaterialNews = newsInfoDownload(mediaId); } } if (newsBatchGetResult.getTotalCount() == 0 || newsBatchGetResult.getItemCount() == 0) { log.info("【獲取微信圖文素材列表】為空!"); return null; } } catch (Exception e) { log.error("\n【獲取微信圖文素材列表】失敗 : {}", e.getMessage()); e.printStackTrace(); } return wxMpMaterialNews; } /** * <pre> * 圖片或聲音永久素材下載 * 根據 media_id 獲取聲音或者圖片的輸入流 * * @author cao_wencao * @param mediaId * 要下載的圖文訊息的id * @return InputStream * </pre> */ public InputStream materialImageOrVoiceDownload(String mediaId) { if (null == mediaId) { return null; } InputStream inputStream = null; try { inputStream = wxMpService.getMaterialService().materialImageOrVoiceDownload(mediaId); if (null != inputStream) { log.info("\n【下載圖片或聲音永久素材】成功 : {}", mediaId); return inputStream; } } catch (Exception e) { log.error("\n【下載圖片或聲音永久素材】失敗 :{} \n媒體ID : {} ", e.getMessage(), mediaId); e.printStackTrace(); } finally { if (null != inputStream) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return inputStream; } /** * <pre> * 獲取視訊永久素材 * * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738729&token=&lang=zh_CN">獲取永久素材</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN * </pre> * * @param mediaId * 永久素材的id */ public WxMpMaterialVideoInfoResult materialVideoInfo(String mediaId) { if (null == mediaId) { return null; } WxMpMaterialVideoInfoResult videoInfoResult = null; try { videoInfoResult = this.wxMpService.getMaterialService().materialVideoInfo(mediaId); if (null != videoInfoResult) { log.info("\n【下載視訊永久素材】成功 : {}", mediaId); return videoInfoResult; } } catch (Exception e) { log.error("\n【下載取視訊永久素材】失敗 : {} \n媒體ID : mediaId", e.getMessage(), mediaId); e.printStackTrace(); } return videoInfoResult; } /** * <pre> * 分頁獲取其他媒體素材列表 * @author cao_wencao * @param type 素材的型別,圖片(image)、視訊(video)、語音 (voice)、圖文(news) * @param offset 從全部素材的該偏移位置開始返回,0表示從第一個素材 返回 * @param count 返回素材的數量,取值在1到20之間 * @return */ public WxMpMaterialFileBatchGetResult materialFileBatchGet(String type, int offset, int count) { if (null == type || offset < 0 || count <= 0) { return null; } WxMpMaterialFileBatchGetResult fileBatchGetResult = null; try { fileBatchGetResult = this.wxMpService.getMaterialService().materialFileBatchGet(type, offset, count); if (fileBatchGetResult.getTotalCount() < 0 || fileBatchGetResult.getItemCount() < 0) { log.error("【獲取微信圖文素材列表】失敗!"); } } catch (Exception e) { log.error("\n【獲取微信圖文素材列表】失敗 : {}", e.getMessage()); e.printStackTrace(); } return fileBatchGetResult; } /** * <pre> * 修改永久圖文素材 根據更新圖文物件更新圖文素材,對於多圖文訊息,如需更新其中某一個,需要設定更新物件中的index屬性 * * @author cao_wencao * @param newsMediaId * 要修改的圖文訊息的id * @param index * 要更新的文章在圖文訊息中的位置(多圖文訊息時,此欄位才有意義),第一篇為0 * @param materialNews * 圖文訊息內容及相關 * @return * </pre> */ public boolean UpdateNewsInfo(String newsMediaId, int index, WxMpMaterialNews materialNews) { // 獲取圖文永久素材的資訊 WxMpMaterialNews wxMpMaterialNews = null; try { wxMpMaterialNews = wxMpService.getMaterialService().materialNewsInfo(newsMediaId); log.info("\n【獲取圖文永久素材】成功 :{}", wxMpMaterialNews.toJson().toString()); } catch (Exception e) { log.error("\n【獲取永久圖文素材】失敗 : {} ", newsMediaId); e.printStackTrace(); } // 圖文素材更新實體類 WxMpMaterialArticleUpdate wxMpMaterialArticleUpdate = new WxMpMaterialArticleUpdate(); // dest article 目的article WxMpMaterialNews.WxMpMaterialNewsArticle article = new WxMpMaterialNewsArticle(); // 更新一條單圖文 List<WxMpMaterialNewsArticle> newsArticleList = materialNews.getArticles(); // source article 來源article2 WxMpMaterialNews.WxMpMaterialNewsArticle article2 = new WxMpMaterialNewsArticle(); for (int i = 0; i < newsArticleList.size(); i++) { article2 = newsArticleList.get(i); article.setContent(article2.getContent()); article.setAuthor(article2.getAuthor()); article.setContentSourceUrl(article2.getContentSourceUrl()); article.setDigest(article2.getDigest()); article.setShowCoverPic(article2.isShowCoverPic()); article.setThumbMediaId(newsMediaId); article.setNeedOpenComment(article2.getNeedOpenComment()); article.setOnlyFansCanComment(article2.getOnlyFansCanComment()); article.setThumbUrl(article2.getThumbUrl()); article.setTitle(article2.getTitle()); article.setUrl(article2.getUrl()); wxMpMaterialArticleUpdate.setMediaId(newsMediaId); wxMpMaterialArticleUpdate.setArticles(article); wxMpMaterialArticleUpdate.setIndex(index); } boolean updateResult = false; try { updateResult = wxMpService.getMaterialService().materialNewsUpdate(wxMpMaterialArticleUpdate); log.info("\n【修改永久圖文素材】成功 : {} ", updateResult); return updateResult; } catch (Exception e) { log.error("\n【修改永久圖文素材】失敗 : {} ", updateResult); e.printStackTrace(); } return updateResult; } /** * <pre> * 獲取圖文永久素材的資訊 * * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738729&token=&lang=zh_CN">獲取永久素材</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=ACCESS_TOKEN * </pre> * * @param mediaId * 永久素材的id */ public WxMpMaterialNews getMaterialInfo(String mediaId) { WxMpMaterialNews wxMpMaterialNews = null; try { wxMpMaterialNews = wxMpService.getMaterialService().materialNewsInfo(mediaId); if (null != wxMpMaterialNews) { log.info("\n【從微信媒體庫獲取圖文永久素材】成功 :{}", wxMpMaterialNews.toJson().toString()); return wxMpMaterialNews; } } catch (WxErrorException e) { log.error("\n【從微信媒體庫獲取永久圖文素材】異常 ,媒體ID :{}", mediaId); e.printStackTrace(); } return null; } /** * <pre> * 獲取各類素材總數 * 開發者可以根據本介面來獲取永久素材的列表,需要時也可儲存到本地。 * 請注意: * 1.永久素材的總數,也會計算公眾平臺官網素材管理中的素材 * 2.圖片和圖文訊息素材(包括單圖文和多圖文)的總數上限為5000,其他素材的總數上限為1000 * 3.呼叫該介面需https協議 * * 詳情請見: <a href="http://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1444738733&token=&lang=zh_CN">獲取素材總數</a> * 介面url格式:https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN * "voice_count":COUNT, 語音總數量 * "video_count":COUNT, 視訊總數量 * "image_count":COUNT, 圖片總數量 * "news_count":COUNT 圖文總數量 * </pre> */ public String materialCount(String materiaType) { WxMpMaterialCountResult resultCount = null; //素材總數返回類 String newsCount = null; // 圖文素材數量 String imageCount = null;// 圖片素材數量 try { resultCount = wxMpService.getMaterialService().materialCount(); JSONObject jsonObject = (JSONObject) JSON.toJSON(resultCount); if (null != resultCount && WxConsts.MaterialType.IMAGE.equals(materiaType)) { imageCount = jsonObject.getString("imageCount"); // 圖片素材總數 log.info("【獲取圖片總數成功,image_Count】:{}條", imageCount); return imageCount; }if (null != resultCount && WxConsts.MaterialType.NEWS.equals(materiaType)) { newsCount = jsonObject.getString("newsCount"); // 圖文素材總數 log.info("【獲取圖文總數成功,news_Count】:{}條", newsCount); return newsCount; } } catch (WxErrorException e) { log.error("\n【獲取各類素材總數】異常 {}", e.getMessage()); e.printStackTrace(); } return null; } }