本文采用倒叙模式.
我写这个主要是因为微信开发文档的说明实在太坑了,为了更多.NET 开发人员能顺利上传微信图片素材,分享一下:
先看看最后的调用成功的方法:
/// <summary>
/// 发送永久图片素材
/// </summary>
/// <param name="filename">文件绝对路径</param>
public static void PushtPicture(string filename)
{
var accessToken = new WxHelper().totalAccessToken;
var postUrl = string.Format("https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={0}", accessToken);
NameValueCollection myCol =new NameValueCollection();
//MD,第三个参数必须是media,,否则上传失败,真操蛋
var response = JsonConvert.DeserializeObject<WxPictureResp>(HttpProcess.HttpUploadFile(postUrl, filename, "media", "image/jpeg", myCol));
}
ok,再上微信版模拟http发送文件:
/// <summary>
/// 模拟http发送文件,这里只发送图片
/// </summary>
/// <param name="url">发送的url地址</param>
/// <param name="">文件绝对路径</param>
/// <param name="paramName">这里必须是media</param>
/// <param name="contentType">是图片,视频还是啥,自己去看http传文件格式</param>
/// <param name="nvc">可不填</param>
/// <returns></returns>
public static string HttpUploadFile(string url, string , string paramName, string contentType, NameValueCollection nvc)
{
string result = string.Empty;
string boundary = "---------------------------" DateTime.Now.Ticks.ToString("x");
byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" boundary "\r\n");
HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
wr.ContentType = "multipart/form-data; boundary=" boundary;
wr.Method = "POST";
wr.KeepAlive = true;
wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
Stream rs = wr.GetRequestStream();
string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
foreach (string key in nvc.Keys)
{
rs.Write(boundarybytes, 0, boundarybytes.Length);
string formitem = string.Format(formdataTemplate, key, nvc[key]);
byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
rs.Write(formitembytes, 0, formitembytes.Length);
}
rs.Write(boundarybytes, 0, boundarybytes.Length);
string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
var pos = .LastIndexOf('/');
var filename = .Substring(pos 1);
string header = string.Format(headerTemplate, paramName, filename, contentType);
byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
rs.Write(headerbytes, 0, headerbytes.Length);
FileStream fileStream = new FileStream(, FileMode., FileAccess.Read);
byte[] buffer = new byte[4096];
int bytesRead = 0;
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
{
rs.Write(buffer, 0, bytesRead);
}
fileStream.();
byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" boundary "--\r\n");
rs.Write(trailer, 0, trailer.Length);
rs.Flush();
rs.();
WebResponse wresp = null;
try
{
wresp = wr.GetResponse();
Stream stream2 = wresp.GetResponseStream();
StreamReader reader2 = new StreamReader(stream2);
result = reader2.ReadToEnd();
}
catch (Exception ex)
{
if (wresp != null)
{
wresp.();
wresp = null;
}
}
finally
{
wr = null;
}
result;
}
最后上工具类:
/// <summary>
/// 微信服务器返回的图片类,只记录成功,失败为null
/// </summary>
public class WxPictureResp
{
/// <summary>
/// 这个就是能用来构造图文消息的 thumb_media_id
/// </summary>
public string media_id { get; ; }
/// <summary>
/// 图片路径,只能在TX系的域名中使用
/// </summary>
public string url { get; ; }
}
可能模拟http发送文件的类有点low,至少应该用StringBuilder的,懒得改了,不差这点性能。
最后
var accessToken = new WxHelper().totalAccessToken;
这个应该不用说,这里采用了Redis缓存,没法用静态构造,只好new啦.