想要新增图文素材,就必须先有图片素材。那么微信上传永久图片素材又是怎么操作的呢?
根据微信文档说明:
重点在于整合media参数,我的代码如下:
然后发布,测试。微信返回:{"errcode":41005,"errmsg":"mediadata missing....} 41005=缺少多媒体文件数据
仔细查看代码,可以得知,media参数我只是把文件的名称传递过去,并没有吧本地文件传递过去,那么,知道了却不知道这个文件数据到底是怎么传递出去的呢?
继续百度ing.....
发现很多网友也是遇到了这个问题,最后又反复查看大神sdk中post请求的写法,重新定义了api接口和实体类,发送创建图片接口,如下:
1、实体类:
public class ResponseNewsModel : WxJsonResult
{
public string media_id { get; set;}//新增永久素材返回的值
public string url { get; set;}//新增永久图片返回url
}
///<summary>
///新增其他类型永久素材图片+视频+语音
///</summary>
///<paramname="accessToken">授权方的access_token</param>
///<paramname="accessToken">媒体文件的类型image、video、voice</param>
///<returns>{"media_id":MEDIA_ID",url": "http://mmbiz.qpic.cn/mmbiz/gLO17UPS6FS2xsypf378iaNhWacZ1G1UplZYWEYfwvuU6Ont96b1roYsCNFwaRrSaKTPCUdBK9DgEHicsKwWCBRQ/0" } 新增的图文消息素材的media_id,新增的图片素材的图片URL(仅新增图片素材时会返回该字段)</returns>
public static ResponseNewsModel addWeixinOpenImg(stringaccessToken, string type, Dictionary<string,string>postData)
{
string urlFormat = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={0}&type="+type;
return CommonJsonSend.SendFile<ResponseNewsModel>(accessToken,urlFormat, postData, WxConfig.TIME_OUT);
}
为了保证代码简洁,这里的很多方法写法都是参考原有的。
2、 sendFile方法:
///<summary>
///这个接口是专门上传媒体文件请求向需要AccessToken的API发送消息的公共方法
///</summary>
///<paramname="accessToken">这里的AccessToken是通用接口的AccessToken,非OAuth的。如果不需要,可以为null,此时urlFormat不要提供{0}参数</param>
///<paramname="urlFormat"></param>
///<paramname="data">如果是Get方式,可以为null</param>
///<paramname="timeOut">代理请求超时时间(毫秒)</param>
///<returns></returns>
public static T SendFile<T>(string accessToken, stringurlFormat, Dictionary<string,string> fileData, inttimeOut = WxConfig.TIME_OUT)
{
var url = string.IsNullOrEmpty(accessToken) ? urlFormat: string.Format(urlFormat, accessToken);
return Post.PostFileGetJson<T>(url, null,fileData, null, timeOut: timeOut);
}
3、最后post发送数据方法【其他接口如转换实体类请参照原大神博客!】:
///<summary>
///发起Post请求
///</summary>
///<typeparamname="T">返回数据类型(Json对应的实体)</typeparam>
///<paramname="url">请求Url</param>
///<paramname="cookieContainer">CookieContainer,如果不需要则设为null</param>
///<paramname="timeOut">代理请求超时时间(毫秒)</param>
///<returns></returns>
public static T PostFileGetJson<T>(string url, CookieContainer cookieContainer = null,Dictionary<string, string> fileDictionary = null, Encoding encoding = null, int timeOut = WxConfig.TIME_OUT)
{
string returnText = HttpUtility.RequestUtility.HttpPost(url,cookieContainer, null, fileDictionary, null,encoding, timeOut: timeOut);
var result = GetResult<T>(returnText);
return result;
}
4、post方法:
///<summary>
///使用Post方法获取字符串结果
///</summary>
///<paramname="url"></param>
///<paramname="cookieContainer"></param>
///<paramname="postStream"></param>
///<paramname="fileDictionary">需要上传的文件,Key:对应要上传的Name,Value:本地文件名</param>
///<paramname="timeOut"></param>
///<returns></returns>
public static string HttpPost(string url, CookieContainer cookieContainer = null, Stream postStream = null, Dictionary<string,string> fileDictionary = null, stringrefererUrl = null, Encoding encoding = null, int timeOut = WxConfig.TIME_OUT)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.Timeout = timeOut;
#region处理Form表单文件上传
var formUploadFile = fileDictionary != null&& fileDictionary.Count > 0;//是否用Form上传文件
if(formUploadFile)
{
//通过表单上传文件
postStream = new MemoryStream();
stringboundary = "----" + DateTime.Now.Ticks.ToString("x");
//byte[] boundarybytes =Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";filename=\"{1}\"\r\nContent-Type:application/octet-stream\r\n\r\n";
foreach (var file in fileDictionary)
{
try
{
var fileName = file.Value;
//准备文件流
using(var fileStream = FileHelper.GetFileStream(fileName))
{
var formdata = string.Format(formdataTemplate, file.Key, /*fileName*/Path.GetFileName(fileName));
var formdataBytes = Encoding.ASCII.GetBytes(postStream.Length== 0 ? formdata.Substring(2, formdata.Length - 2) : formdata);//第一行不需要换行
postStream.Write(formdataBytes,0, formdataBytes.Length);
//写入文件
byte[] buffer = newbyte[1024];
int bytesRead = 0;
while((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
postStream.Write(buffer, 0, bytesRead);
}
}
}
catch(Exception ex)
{
throw ex;
}
}
//结尾
var footer = Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
postStream.Write(footer, 0, footer.Length);
request.ContentType = string.Format("multipart/form-data; boundary={0}",boundary);
}
else
{
request.ContentType = "application/x-www-form-urlencoded";
}
#endregion
request.ContentLength = postStream != null? postStream.Length : 0;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
request.KeepAlive = true;
if(!string.IsNullOrEmpty(refererUrl))
{
request.Referer = refererUrl;
}
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1;WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57Safari/537.36";
#region输入二进制流
if(postStream != null)
{
postStream.Position = 0;
//直接写入流
Stream requestStream = request.GetRequestStream();
byte[] buffer = newbyte[1024];
int bytesRead = 0;
while ((bytesRead =postStream.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}
postStream.Close();//关闭文件访问
}
#endregion
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using(Stream responseStream = response.GetResponseStream())
{
using (StreamReadermyStreamReader = newStreamReader(responseStream,encoding ?? Encoding.GetEncoding("utf-8")))
{
string retString =myStreamReader.ReadToEnd();
return retString;
}
}
}
5、最后测试调用:
public string addImg(){
string filepath = Server.MapPath("~/images/maxlaw.png");
stringtype = "image";
Dictionary<string, string>fileData = newDictionary<string,string>();
fileData.Add("media",filepath);//事先写好参数
ResponseNewsModel imgData = DoWeixinOpenApi.addWeixinOpenImg(Golbal_authorizer_accessToken,type, fileData);
if (imgData.errmsg != "ok")
{
FileHelper.LogToTxt("发生什么错误了!" +imgData.errmsg);
}
FileHelper.LogToTxt("上传永久图片素材测试啊:::"+ imgData.media_id + "<br>地址是:::" + imgData.url);
return"ok";
}
打开日志查看,返回结果:
上传永久素材测试啊:::YKeHO6zG3cS_4f61bI0jKe_HFy0......4YnWnwFs<br>地址是:::https://mmbiz.qlogo.cn/mmbiz/oXGwXicXmia5XySWuNbR......cA3FSvzicc9Fw8EictQ2kbTvWlkLIqVlfLiaTJ8v1EVPQicS25Dw/0?wx_fmt=png2016-05-1318:16:20