微信公众号开发者文档里面发送消息-被动回复消息,右边能够点击回复图片消息。java
若是是第一次开发微信公众号的小伙伴第一次看到这么短一段说明文字的时候可能一会儿就懵逼了,由于根本就不知道如何去获取这个MediaId。这也是微信公众号开发文档的一个比较坑爹的地方,由于单纯看这一页根本就不知道如何去获取这个参数,并且开发文档有些地方json
的参数仍是有错误的。缓存
这个时候就须要点击素材管理-新增临时素材那里去看一下相关接口的地址和调用方法。安全
若是对文件的上传和下载不是很熟的朋友,能够参考慕课网中的文件上传和下载的课程服务器
这个课程里面有讲文件上传须要设置的一些什么像头文件啊分界符啊微信
运行测试类WeixinTest.java以后控制台打印出错误信息微信开发
得知此错误以后返回去看微信公众号开发文档里面的接口返回码说明,看一看全局返回码说明app
找到48001错误。原来是测试
由于我这个微信公众号是我的订阅号,因此没有得到该接口的权限。ui
而后就须要使用咱们以前讲过的测试号了,须要把测试号的开发者ID和开发者密钥替换掉程序中的我的订阅号的微信开发者ID和开发者密钥
假如说你手上有一套微信公众号的代码,你只须要替换掉appid和appsecret以及tocken。这三个地方代码里面和后台配置只要一致的话就能够了。
再次运行测试类WeixinTest.java,能够获得返回结果media_id
顺便把JS接口安全域名也给修改了,填上百度云服务器上面本应用的域名
提交代码以后报错
估计是token票据失效了,从新获取token票据和MediaId
仍是报错。。。
票据能够有效两个小时,媒体文件能够在微信后台保存3天,即3天后MediaId失效。若是这样都仍是报报错,那应该是最复杂的上传本地媒体文件到微信后台服务器的代码有错误,图片根本就没有发送到微信后台那里去。
发现了这一个代码有错,把请求头信息Keep-Aive改为Keep-Alive以后仍是报错
原来是回复图片消息要先关注本身申请的接口测试号公众号以后在测试号进行测试才能够,若是使用本身的我的订阅号是不能够提供服务的
哈哈,这个就是微信开发文档中比较坑爹的一个地方。哈哈哈啊哈啊哈哈哈。。。
下面贴一下主要的代码吧:
WeixinUtil.java的媒体文件上传代码
//下面写一个文件上传的代码
public static String upload(String filePath,String accessToken,String type) throws IOException{
//这里须要传递三个参数:文件所在的路径,票据,文件的类型
//首先进来须要对文件路径进行判断,是否存在
File file = new File(filePath);
if(!file.exists()||!file.isFile()){
throw new IOException("文件不存在");
}
String url = UPLOAD_URL.replace("ACCESS_TOKEN",accessToken).replace("TYPE",type);//而后须要对接口地址的两个参数access_tocken和type进行赋值
URL urlObj = new URL(url);
//链接
HttpURLConnection con = (HttpURLConnection) urlObj.openConnection();
//首先是以POST方式进行提交
con.setRequestMethod("POST");
con.setDoInput(true);//进行输入输出
con.setDoOutput(true);
con.setUseCaches(false);//若是是POST方式要设置忽略它的缓存
//设置请求头信息
con.setRequestProperty("Connection", "Keep-Alive");
con.setRequestProperty("Charset", "UTF-8");
//设置边界
String BOUNDARY = "-------"+System.currentTimeMillis();
con.setRequestProperty("Content-Type","multipart/form-data;boundary="+BOUNDARY);
StringBuilder sb = new StringBuilder();
sb.append("--");
sb.append(BOUNDARY);
sb.append("\r\n");
sb.append("Content-Dispoistion:form-data;name=\"file\";filename=\""+file.getName()+"\"\r\n");
sb.append("Content-Type:application/octet-stream\r\n\r\n");
byte[] head = sb.toString().getBytes("utf-8");
//而后经过输出流的方式进行输出
//获取输出流
OutputStream out = new DataOutputStream(con.getOutputStream());
//输出表头
out.write(head);
//文件正文部分
//把文件以流文件的方式 推入到url中
DataInputStream in = new DataInputStream(new FileInputStream(file));
int bytes = 0;
byte[] bufferOut = new byte[1024];
while((bytes = in.read(bufferOut))!=-1){
out.write(bufferOut, 0, bytes);
}
in.close();
//结尾部分
byte[] foot = ("\r\n--"+ BOUNDARY +"--\r\n").getBytes("utf-8");//定义最后数据分隔线
out.write(foot);
out.flush();
out.close();
StringBuffer buffer = new StringBuffer();
BufferedReader reader = null;
String result = null;
//定义BufferedReader输入流来读取URL的响应
//请求成功之后咱们要在输入流里面去拿它的响应结果
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
try{
while((line = reader.readLine())!=null){
buffer.append(line);
}
if(result == null){
result = buffer.toString();
}
}catch(IOException e){
e.printStackTrace();
}finally{
if(reader!=null){
reader.close();
}
}
JSONObject jsonObj = JSONObject.fromObject(result);//把结果转成JSON格式
System.out.println(jsonObj);
String mediaId = jsonObj.getString("media_id");
return mediaId;
}
WeixinTest.java 测试代码
package com.imooc.test;
import java.io.IOException;
import com.imooc.po.AccessTocken;
import com.imooc.util.WeixinUtil;
public class WeixinTest {
public static void main(String[] args) {
AccessTocken token = WeixinUtil.getAccessTocken();
System.out.println("票据:"+token.getToken());
System.out.println("有效时间:"+token.getExpiresIn());
String path = "D:/imooc.jpg";
try {
String mediaId = WeixinUtil.upload(path,token.getToken(),"image");
System.out.println(mediaId);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Image.java
package com.imooc.po;
public class Image {
private String MediaId;//和发送消息-被动回复消息-回复图片消息的返回的一段XML代码里面的一个字段MediaId同样
public String getMediaId() {
return MediaId;
}
public void setMediaId(String mediaId) {
MediaId = mediaId;
}
}
ImageMessage.java
package com.imooc.po;
public class ImageMessage extends BaseMessage{
//private Image image;//这里的大小写是很重要的 不然后面将javabean转为XML的时候没法识别
private Image Image;
public Image getImage() {
return Image;
}
public void setImage(Image image) {
//this.Image = image;
Image = image;
}
}
Messageutil.java的组装图片消息
/**
*
* 图片消息的组装
* @param toUserName
* @param fromUserName
* @return
*/
public static String initImageMessage(String toUserName,String fromUserName){//接收方和发送方
String message = null;
Image image = new Image();
//image.setMediaId("idKpa1NXpmkbUpntpH8nMwPj3cTTiH02-B_ZE57LOt9fWOPVKvrxp5BKokk8wUNi");
image.setMediaId("aycSC7SSzXpVnz45Li_Qg1nUl4pHZpyNeHKVg70Ih7z9RmvUBA4yyT72FjFjOiu_");//再次上传图片,实际上是从新获取票据,从新获取MediaId
ImageMessage imageMessage = new ImageMessage();
imageMessage.setFromUserName(toUserName);
imageMessage.setToUserName(fromUserName);
imageMessage.setMsgType(MESSAGE_IMAGE);//使用常量而不是字符串,这样可维护性比较强 消息的类型是图片
imageMessage.setCreateTime(new Date().getTime());//仍是咱们的当前时间
imageMessage.setImage(image);
message = imageMessageToXml(imageMessage);//将JavaBean转为XML
return message;
}
以及
/**
* 图片消息转为XML
* @param imageMessage
* @return
*/
public static String imageMessageToXml(ImageMessage imageMessage){
XStream xstream = new XStream();
xstream.alias("xml", imageMessage.getClass());
return xstream.toXML(imageMessage);
}
最后就在Servlet写业务逻辑