素材CRUD的Api及介绍参见微信官方文档:
Java实现(Controller实现):
package ***;
import ***.Result;
import ***.ResultUtils;
import ***.WeChatAccessToken;
import ***.api.wechat.domain.WeChatResponseToken;
import ***.dao.mybatis.wechat.WeChatCustomerMapper;
import ***.dao.mybatis.wechat.domain.WeChatSetting;
import ***.service.impl.WeChatAccessTokenServiceImpl;
import ***..utils.HttpClientUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.Arrays;
@RestController
@RequestMapping("/api/ugg/pushchannel/admin")
@Slf4j
public class WeChatAdminController {
// 上传微信永久素材的url
private static final String UPLOAD_FOREVER_MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE";
private static final String DELETE_FOREVER_MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/material/del_material?access_token=ACCESS_TOKEN";
private static final String COUNT_FOREVER_MEDIA_URL = "https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN";
private static final long MAX_SIZE = 1024 * 1024 * 2;
private static final String SUPPORTED_FORMAT = "jpeg,jpg";
@Autowired
WeChatCustomerMapper weChatCustomerMapper;
@Autowired
WeChatAccessTokenServiceImpl weChatAccessTokenService;
/**
* @note:上传永久素材
* @Api:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Adding_Permanent_Assets.html
* */
@RequestMapping(value = "/uploadFile", method = RequestMethod.POST)
public Result uploadFile(@RequestParam("file")MultipartFile multiFile, @RequestParam("type")Integer type) throws IOException {
String[] split = multiFile.getOriginalFilename().split("\\.");
String suffixName = split[split.length-1];
boolean validPic = this.isValidPic(multiFile.getSize(), suffixName);
if (!validPic) {
return ResultUtils.fail("图片大小或格式不符");
}
//查找type对应的公众号(或小程序)
String accessToken = getAccessTokenByType(type);
if ("".equals(accessToken)) {
ResultUtils.fail("未找到对应type的配置信息");
}
String replacedUrl = UPLOAD_FOREVER_MEDIA_URL
.replace("ACCESS_TOKEN", accessToken)
.replace("TYPE", "image");
JSONObject jsonObject = connectHttpsByPost(replacedUrl,
multiFile.getResource().getInputStream(), multiFile.getOriginalFilename());
log.info("微信素材上传结果:[{}]", jsonObject.toString());
if (jsonObject != null && jsonObject.containsKey("media_id")) {
String media_id = jsonObject.getString("media_id");
return ResultUtils.success(media_id);
}
return ResultUtils.fail("素材图片上传失败");
}
/**
* @note:删除永久素材
* @Api:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Deleting_Permanent_Assets.html
*/
@RequestMapping(value = "/deleteFile", method = RequestMethod.POST)
public Result deleteFile(@RequestParam("type") Integer type, @RequestParam("media_id") String media_id) throws IOException {
//查找type对应的公众号(或小程序)
String accessToken = getAccessTokenByType(type);
if ("".equals(accessToken)) {
ResultUtils.fail("未找到对应type的配置信息");
}
String replacedUrl = DELETE_FOREVER_MEDIA_URL
.replace("ACCESS_TOKEN", accessToken);
com.alibaba.fastjson.JSONObject jsonParam = new com.alibaba.fastjson.JSONObject();
jsonParam.put("media_id", media_id);
com.alibaba.fastjson.JSONObject jsonObject = HttpClientUtils.doPostJson(replacedUrl, jsonParam);
log.info("微信素材删除结果:[{}]", jsonObject.toString());
return ResultUtils.success(jsonObject);
}
/**
* @note:获取所有素材count
* @Api:https://developers.weixin.qq.com/doc/offiaccount/Asset_Management/Get_the_total_of_all_materials.html
* */
@RequestMapping(value = "/getMaterialCount", method = RequestMethod.GET)
public Result getMaterialCount(@RequestParam("type") Integer type) throws IOException {
String accessToken = getAccessTokenByType(type);
if ("".equals(accessToken)) {
ResultUtils.fail("未找到对应type的配置信息");
}
String replacedUrl = COUNT_FOREVER_MEDIA_URL
.replace("ACCESS_TOKEN", accessToken);
com.alibaba.fastjson.JSONObject jsonObject = HttpClientUtils.doGetJson(replacedUrl);
log.info("获取到微信所有素材count:[{}]", jsonObject.toString());
return ResultUtils.success(jsonObject);
}
/**
* 根据type获取access_token
* @param type
* @return String
* */
private final String getAccessTokenByType(Integer type) {
WeChatSetting setting = weChatCustomerMapper.getWeChatSetting(type);
if (null == setting || StringUtils.isBlank(setting.getAppId()) || StringUtils.isBlank(setting.getAppSecret())) {
return "";
}
WeChatAccessToken weChatAccessToken = new WeChatAccessToken();
weChatAccessToken.setAppid(setting.getAppId());
weChatAccessToken.setSecret(setting.getAppSecret());
Result<WeChatResponseToken> weChatResponseTokenResult = weChatAccessTokenService.weChatAccessToken(weChatAccessToken);
return weChatResponseTokenResult.getData().getAccess_token();
}
/**
* 图片是否符合微信规范
* @param size
* @param suffixName
* @return boolean
*/
public Boolean isValidPic(long size, String suffixName) {
if (size > MAX_SIZE) {
log.info("文件太大,文件的大小最大为2M,请重新上传!");
return false;
}
if (!Arrays.asList(SUPPORTED_FORMAT.split(",")).contains(suffixName)) {
log.info("图片格式不支持,请选择jpeg/jpg的任意一种!");
return false;
}
return true;
}
/**
* 请求微信服务器 Post form-data
* * 把文件上传到指定url上去
* * @param url 上传地址
* * @param file 待上传文件
* */
public static JSONObject connectHttpsByPost(String url, InputStream file,String fileName) throws IOException {
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
HttpPost httppost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(200000).setSocketTimeout(200000).build();
httppost.setConfig(requestConfig);
//通过addBinaryBody传入file
HttpEntity reqEntity = MultipartEntityBuilder.create()
.addBinaryBody("media", inputTobyte(file), ContentType.DEFAULT_BINARY,
fileName).build();
httppost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httppost);
try {
System.out.println(response.getStatusLine());
HttpEntity resEntity = response.getEntity();
if (resEntity != null) {
String responseEntityStr = EntityUtils.toString(response.getEntity());
log.info("responseEntityStr=[{}]",responseEntityStr);
return JSONObject.fromObject(responseEntityStr);
}
EntityUtils.consume(resEntity);
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
private static final byte[] inputTobyte(InputStream inStream)
throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();
return in2b;
}
}