学习记录
经过一段时间的学习与使用,这版应该是最终版了,以后大概率不会调整了
以下的方法都是里面最的核心方法,有兴趣可以直接搜索看一下
Send、SendDownload、GetJsonContent、GetStringContent、GetMultipartFormDataContent
HttpClient进行post,get请求
代码拷到项目中就能用:
.
要引用以下:
.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net;
using System.Text;
using System.Net.Http.Headers
/// <summary>
/// HttpClient
/// </summary>
public class HttpClientHelper
{
/// <summary>
/// 当响应状态码不正确时执行事件
/// </summary>
/// <remarks>
/// 假如该事件不存在 则抛异常
/// </remarks>
public event Action<HttpResponseMessage> SendErrorCode;
/// <summary>
/// 超时时间
/// </summary>
public TimeSpan Timeout = new TimeSpan(0, 1, 0);
#region Get
/// <summary>
/// Get请求(普通请求)
/// </summary>
/// <param name="url">地址</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public string Get(string url, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return SendString(client => client.GetAsync(url), action, httpClientHandler);
}
#endregion
#region 下载文件 Download
/// <summary>
/// 下载文件(Get请求)
/// </summary>
/// <param name="url">地址</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public DownloadFile DownloadGet(string url, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return SendDownload(client => client.GetAsync(url), action, httpClientHandler);
}
/// <summary>
/// 下载文件(Post请求)
/// </summary>
/// <param name="url">地址</param>
/// <param name="Content">HttpContent示例:GetJsonContent(encoding, JsonData)</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public DownloadFile DownloadPost(string url, HttpContent Content, Action<HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return SendDownload(client => client.PostAsync(url, Content), action, httpClientHandler);
}
#endregion
#region Form
/// <summary>
/// Post请求(普通请求)
/// </summary>
/// <param name="url">地址</param>
/// <param name="parameters">参数</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public string PostForm(string url, Dictionary<string, object> parameters = null, Action<HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return SendString(client => client.PostAsync(url, GetStringContent(parameters)), action, httpClientHandler);
}
#endregion
#region Json
/// <summary>
/// Post请求(Stream方式请求)
/// </summary>
/// <param name="url">地址</param>
/// <param name="encoding">编码</param>
/// <param name="JsonData">Json数据</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public string PostJson(string url, Encoding encoding, string JsonData = null, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
var content = GetJsonContent(encoding, JsonData);
return SendString(client => client.PostAsync(url, content), action, httpClientHandler);
}
#endregion
#region MultipartForm
/// <summary>
/// Post请求(带文件,假如是文件集合,则把PostHelper的参数名定义为同一个)
/// </summary>
/// <param name="url">链接</param>
/// <param name="Parameters">参数</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns></returns>
public string PostMultipartForm(string url, List<PostHelper> Parameters, Action<HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return SendString(client => client.PostAsync(url, GetMultipartFormDataContent(Parameters)), action, httpClientHandler);
}
#endregion
#region GetContent
/// <summary>
/// 获取Josn形式的Body上下文
/// </summary>
/// <param name="encoding">字符编码</param>
/// <param name="JsonData">json字符串</param>
/// <returns></returns>
public static StreamContent GetJsonContent(Encoding encoding, string JsonData = "{}")
{
byte[] buffer = encoding.GetBytes(JsonData);
MemoryStream stream = new MemoryStream(buffer);
var content = new StreamContent(stream);
//ByteArrayContent content = new ByteArrayContent(buffer);
//设置ContentType
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
return content;
}
/// <summary>
/// 获取Form的Content
/// </summary>
/// <param name="parameters">键值对参数</param>
/// <returns></returns>
public static StringContent GetStringContent(Dictionary<string, object> parameters)
{
string param = "";
if (parameters != null)
{
StringBuilder sb = new StringBuilder();
foreach (var item in parameters)
{
if (sb.Length == 0)
sb.AppendFormat("{0}={1}", item.Key, item.Value);
else
sb.AppendFormat("&{0}={1}", item.Key, item.Value);
}
param = sb.ToString();
}
var content = new StringContent(param);
//设置ContentType
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/x-www-form-urlencoded");
return content;
}
/// <summary>
/// 获取流媒体的Content
/// </summary>
/// <param name="Parameters">流媒体相关参数</param>
/// <returns></returns>
public static MultipartFormDataContent GetMultipartFormDataContent(List<PostHelper> Parameters)
{
//定义content
var content = new MultipartFormDataContent();
foreach (var param in Parameters)
{
switch (param.Type)
{
case ParameterType.Path:
{
string path = param.Value.ToString();
string fName = Path.GetFileName(path);
FileStream fs = File.OpenRead(path);
StreamContent streamContent = new StreamContent(fs);
SetHttpContent(streamContent, param);
content.Add(streamContent, param.Name, fName);
}
break;
case ParameterType.Stream:
{
StreamContent streamContent = new StreamContent((Stream)param.Value);
SetHttpContent(streamContent, param);
content.Add(streamContent, param.Name, param.FileName);
}
break;
case ParameterType.Normal:
default:
{
content.Add(new StringContent(param.Value.ToString()), param.Name);
}
break;
}
}
return content;
}
/// <summary>
/// 设置HttpContent
/// </summary>
/// <param name="httpContent">要设置的流媒体HttpContent</param>
/// <param name="postHelper">Post请求时的流媒体帮助类</param>
/// <param name="ContentType">默认ContentType参数</param>
private static void SetHttpContent(HttpContent httpContent, PostHelper postHelper, string ContentType = "application/octet-stream")
{
if (string.IsNullOrEmpty(postHelper.ContentType))
{
postHelper.ContentType = ContentType;
}
if (!string.IsNullOrEmpty(postHelper.ContentType))
{
httpContent.Headers.Add("Content-Type", postHelper.ContentType);
}
}
#endregion
#region 公开的HttpClient相关方法
/// <summary>
/// 获取HttpClient
/// </summary>
/// <param name="httpClientHandler">可以设置cookie等参数</param>
/// <returns></returns>
public static HttpClient GetHttpClient(HttpClientHandler httpClientHandler = null)
{
return httpClientHandler == null ? new HttpClient() : new HttpClient(httpClientHandler);
}
/// <summary>
/// 发送请求
/// </summary>
/// <param name="client">http请求客户端</param>
/// <param name="func">指示如何进行http请求</param>
/// <returns></returns>
public HttpResponseMessage Send(HttpClient client, Func<HttpClient, System.Threading.Tasks.Task<HttpResponseMessage>> func)
{
//没加这段代码,有的请求会报'AggregateException'错误
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidate;
try
{
//一分钟超时
client.Timeout = this.Timeout;
HttpResponseMessage response = func(client).Result;
if (response.StatusCode != HttpStatusCode.OK)
{
if (SendErrorCode == null)
{
response.EnsureSuccessStatusCode();//用来抛异常的
}
else
{
SendErrorCode(response);
}
}
return response;
}
catch (AggregateException e)
{
//foreach (var item in e.InnerExceptions)
//{
//}
throw e;
//strResult = default(T);
}
catch (Exception e)
{
//Console.WriteLine(e.Message);
//strResult = default(T);
throw e;
//strResult = e.Message;
}
finally
{
client.Dispose();
}
}
/// <summary>
/// Post请求(Stream方式请求)
/// </summary>
/// <param name="func">指示如何进行http请求</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public string SendString(Func<HttpClient, System.Threading.Tasks.Task<HttpResponseMessage>> func, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
return Send(func, Response => Response.Content.ReadAsStringAsync(), action, httpClientHandler);
}
/// <summary>
/// 发送下载文件请求
/// </summary>
/// <param name="func">指示如何进行http请求</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns>返回字符串</returns>
public DownloadFile SendDownload(Func<HttpClient, System.Threading.Tasks.Task<HttpResponseMessage>> func, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
DownloadFile downloadFile = null;
var result = Send(func, Response =>
{
downloadFile = new DownloadFile
{
StreamFile = null,
//Bol = Response.Content.Headers.ContentLength == 0,
CharSet = Response.Content.Headers.ContentType.CharSet
};
downloadFile.IsFile = string.IsNullOrEmpty(downloadFile.CharSet);
if (downloadFile.IsFile)
{
if (Response.Content.Headers.ContentDisposition != null)
{
downloadFile.FileName = Response.Content.Headers.ContentDisposition.FileName;
}
else
{
var AbsoluteUri = Response.RequestMessage.RequestUri.AbsoluteUri;
var index = AbsoluteUri.IndexOf('?');
string StartString = AbsoluteUri;
if (index != -1)
{
StartString = StartString.Substring(0, index + 1);
}
index = StartString.LastIndexOf('/');
downloadFile.FileName = index != -1 ? StartString.Substring(index) : StartString;
downloadFile.FileName = downloadFile.FileName.TrimStart('/').TrimEnd('?');
}
}
return Response.Content.ReadAsStreamAsync();
}, action, httpClientHandler);
if (downloadFile.IsFile)
{
downloadFile.StreamFile = result;
}
else
{
var encoding = Encoding.GetEncoding(downloadFile.CharSet);
byte[] buffer = new byte[result.Length];
result.Read(buffer, 0, buffer.Length);
downloadFile.Message = encoding.GetString(buffer);
result.Close();
result.Dispose();
}
return downloadFile;
}
#endregion
#region 私有的发送http请求操作
/// <summary>
/// 远程证书验证
/// </summary>
private static bool RemoteCertificateValidate(object sender, System.Security.Cryptography.X509Certificates.X509Certificate cert, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors error)
{
return true;
}
/// <summary>
/// 发送请求(私有 -- .net封装的Http常见请求)
/// </summary>
/// <param name="func">指示如何进行http请求</param>
/// <param name="FuncResult">如何操作 对方返回的结果集</param>
/// <param name="action">可以用来设置请求头</param>
/// <param name="httpClientHandler">可以设置cookie之类的</param>
/// <returns></returns>
private T Send<T>(Func<HttpClient, System.Threading.Tasks.Task<HttpResponseMessage>> func, Func<HttpResponseMessage, System.Threading.Tasks.Task<T>> FuncResult, Action<System.Net.Http.Headers.HttpRequestHeaders> action = null, HttpClientHandler httpClientHandler = null)
{
var client = GetHttpClient(httpClientHandler);
if (action != null)
{
action(client.DefaultRequestHeaders);
}
var response = Send(client, func);
return FuncResult(response).Result;
}
#endregion
#region 类、枚举
/// <summary>
/// Post请求帮助类
/// </summary>
public class PostHelper
{
/// <summary>
///
/// </summary>
public PostHelper() { }
/// <summary>
/// 实例化非文件的参数
/// </summary>
/// <param name="Name">参数名</param>
/// <param name="Value">参数值</param>
public PostHelper(string Name, object Value)
{
this.Name = Name;
this.Value = Value;
this.Type = ParameterType.Normal;
}
/// <summary>
/// 实例化文件参数
/// </summary>
/// <param name="Name">参数名</param>
/// <param name="Value">参数值</param>
/// <param name="Type">参数类型</param>
/// <param name="ContentType">ContentType,有些文件使用默认值会有问题</param>
/// <param name="FileName">文件名(传文件流时必传)</param>
public PostHelper(string Name, object Value, ParameterType Type, string ContentType = "application/octet-stream", string FileName = null)
{
this.Name = Name;
this.Value = Value;
this.Type = Type;
this.FileName = FileName;
this.ContentType = ContentType;
}
/// <summary>
/// 参数名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 参数值
/// </summary>
public object Value { get; set; }
/// <summary>
/// 参数类型
/// </summary>
public ParameterType Type { get; set; }
/// <summary>
/// 文件名(传文件流时必传)
/// </summary>
public string FileName { get; set; }
/// <summary>
/// ContentType
/// </summary>
/// <remarks>
/// 为空时取默认值,否则取当前赋值
/// </remarks>
public string ContentType { get; set; }
}
/// <summary>
/// Post请求帮助类
/// </summary>
public enum ParameterType
{
/// <summary>
/// 非文件的参数
/// </summary>
Normal = 0,
/// <summary>
/// 路径
/// </summary>
Path = 1,
/// <summary>
/// 文件流
/// </summary>
Stream = 2,
}
/// <summary>
/// 文件下载帮助类
/// </summary>
public class DownloadFile
{
/// <summary>
/// 文件
/// </summary>
public Stream StreamFile { get; internal set; }
/// <summary>
/// 文件
/// </summary>
public string CharSet { get; internal set; }
/// <summary>
/// 文件
/// </summary>
public string FileName { get; internal set; }
/// <summary>
/// 是否是文件
/// </summary>
public bool IsFile { get; internal set; }
/// <summary>
/// 消息
/// </summary>
public string Message { get; internal set; }
/// <summary>
/// 保存文件(相同文件直接覆盖)
/// </summary>
/// <param name="FilePath">文件路径 示例1:"D:\1.txt" 示例2:"D:\"+FileName</param>
public void Save(string FilePath)
{
using (var fileStream = new System.IO.FileStream(FilePath, System.IO.FileMode.Create, FileAccess.Write))
{
StreamFile.CopyTo(fileStream);
}
}
}
#endregion
}