C#使用HttpClient进行post,get请求

这篇博客详细记录了如何在C#中使用HttpClient类进行GET和POST请求,包括普通请求、文件下载、JSON数据和表单数据的处理。提供了完整的代码示例,涵盖了设置超时、请求头、处理错误等多个方面。
摘要由CSDN通过智能技术生成

学习记录

经过一段时间的学习与使用,这版应该是最终版了,以后大概率不会调整了
以下的方法都是里面最的核心方法,有兴趣可以直接搜索看一下
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
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值