zoukankan      html  css  js  c++  java
  • HttpWebRequest、HttpWebResponse、HttpClient、WebClient等http网络访问类的使用示例汇总

    工作中长期需要用到通过HTTP调用API以及文件上传下载,积累了不少经验,现在将各种不同方式进行一个汇总。

    首先是HttpWebRequest:

    /// <summary>
    /// 向服务器发送Request
    /// </summary>
    /// <param name="url">字符串</param>
    /// <param name="method">枚举类型的方法Get或者Post</param>
    /// <param name="body">Post时必须传值</param>
    /// <param name="timeoutSeconds">超时时间,单位秒</param>
    /// <returns></returns>
    public static string Request(string url, MethodEnum method, string body = "", int timeoutSeconds = 15000)
    {
        if (!IsConnectedInternet())
            return "网络连接错误,请稍后再试。";
    
        try
        {
            GC.Collect();
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Timeout = timeoutSeconds;
            request.Method = method.ToString();
            21         //如果是Post的话,则设置body
            if (method == MethodEnum.POST)
            {
                request.ContentType = "application/json";
                request.KeepAlive = false;
                byte[] requestBody = Encoding.UTF8.GetBytes(body);
                request.ContentLength = requestBody.Length;
    
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(requestBody, 0, requestBody.Length);
            }
    
            return Response(request);
        }
        catch (Exception ex)
        {
            if (ex.InnerException != null)
                return ex.InnerException.Message;
            if (ex.Message.Contains("已取消一个任务"))
                return "连接服务器超时,请重试";
            if (ex.Message.Contains("404"))
                return "连接服务器404,请重试";
            return ex.Message;
        }
    }

    然后是HttpWebResponse:

    /// <summary>
    /// 返回Response数据
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    private static string Response(HttpWebRequest request)
    {
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    
        string jsonRead = "";
    
        if (response.StatusCode != HttpStatusCode.OK)
        {
            return response.StatusCode.ToString();
        }
        //接收过程
        if (response.GetResponseStream() != null)
        {
            StreamReader myStreamReader = new StreamReader(response.GetResponseStream() ?? Stream.Null, Encoding.UTF8);
            jsonRead = myStreamReader.ReadToEnd();
            myStreamReader.Close();
        }
        response.Close();
        request.Abort();
    
        return jsonRead;
    }

     上面两个方法需要配合使用,皆为同步方式。当然也可以将上面两个方法合并到一个方法中,可以参见接下来这个方法。

    另外是使用HttpWebRequest和HttpWebResponse进行文件上传,采用同步方法异步回调方式:

    public static void UploadFile(string url, string filePath, string fileName, Action<string> callback)
    {
        // 时间戳,用做boundary
        string timeStamp = DateTime.Now.Ticks.ToString("x");
    
        //根据uri创建HttpWebRequest对象
        HttpWebRequest httpReq = (HttpWebRequest)WebRequest.Create(new Uri(url));
        httpReq.Method = "POST";
        httpReq.AllowWriteStreamBuffering = false; //对发送的数据不使用缓存
        httpReq.Timeout = 300000;  //设置获得响应的超时时间(300秒)
        httpReq.ContentType = "multipart/form-data; boundary=" + timeStamp;
    
        //文件
        FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
        BinaryReader binaryReader = new BinaryReader(fileStream);
    
        //头信息
        string boundary = "--" + timeStamp;
        string dataFormat = boundary + "
    Content-Disposition: form-data; name="{0}";filename="{1}"
    Content-Type:application/octet-stream
    
    ";
        string header = string.Format(dataFormat, "file", Path.GetFileName(filePath));
        byte[] postHeaderBytes = Encoding.UTF8.GetBytes(header);
    
        //结束边界
        byte[] boundaryBytes = Encoding.ASCII.GetBytes("
    --" + timeStamp + "--
    ");
    
        long length = fileStream.Length + postHeaderBytes.Length + boundaryBytes.Length;
    
        httpReq.ContentLength = length;//请求内容长度
    
        try
        {
            //每次上传4k
            int bufferLength = 4096;
            byte[] buffer = new byte[bufferLength];
    
            //已上传的字节数
            long offset = 0;
            int size = binaryReader.Read(buffer, 0, bufferLength);
            Stream postStream = httpReq.GetRequestStream();
    
            //发送请求头部消息
            postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
    
            while (size > 0)
            {
                postStream.Write(buffer, 0, size);
                offset += size;
                size = binaryReader.Read(buffer, 0, bufferLength);
            }
    
            //添加尾部边界
            postStream.Write(boundaryBytes, 0, boundaryBytes.Length);
            postStream.Close();
    
            string returnValue = "";
            //获取服务器端的响应
            using (HttpWebResponse response = (HttpWebResponse)httpReq.GetResponse())
            {
                Stream receiveStream = response.GetResponseStream();
                StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
                returnValue = readStream.ReadToEnd();
                response.Close();
                readStream.Close();
            }
            
            callback?.Invoke(returnValue);
        }
        catch (Exception)
        {
            callback?.Invoke("");
        }
        finally
        {
            fileStream.Close();
            binaryReader.Close();
        }
    }

    上面还用到一个enum叫MethodEnum,包含GET和POST两个枚举值。

    还有一个比较特殊的POST方法:

    public static string HttpPostFormData(string url, Dictionary<string, string> dic)
    {
        try
        {
            GC.Collect();
            // 时间戳,用做boundary
            string timeStamp = DateTime.Now.Ticks.ToString("x");
            string boundary = "----" + timeStamp;
    
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = WebRequestMethods.Http.Post;
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.KeepAlive = true;
            request.Timeout = 3000;
    
            var stream = new MemoryStream();
    
            //头信息
            string dataFormat = "--" + boundary + "
    Content-Disposition: form-data; name="{0}"
    
    {1}
    ";
            foreach (string key in dic.Keys)
            {
                string s = string.Format(dataFormat, key, dic[key]);
                byte[] data = Encoding.UTF8.GetBytes(s);
                stream.Write(data, 0, data.Length);
            }
    
            //结束边界
            byte[] boundaryBytes = Encoding.ASCII.GetBytes("--" + boundary + "--");
            stream.Write(boundaryBytes, 0, boundaryBytes.Length);
    
            request.ContentLength = stream.Length;//请求内容长度
    
            Stream requestStream = request.GetRequestStream(); //写入请求数据
            stream.Position = 0L;
            stream.CopyTo(requestStream);
            stream.Close();
    
            requestStream.Close();
    
            return Response(request);
        }
        catch (Exception e)
        {
            return e.Message;
        }
    }

    然后是HttpClient,这个类提供的都是异步方法,下面包含了POST、GET、PUT、DELETE四个方法,还有一个SEND方法稍加改动即可实现:

    public static async void AsyncPost(string url, string body, Action<RequestResult> callback, int timeoutSeconds = 10)
    {
        var requestResult = new RequestResult();
        if (!IsConnectedInternet())
        {
            requestResult.Message = "网络连接错误,请稍后再试。";
            callback?.Invoke(requestResult);
            return;
        }
    
        try
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("authorization", "LJQfL1A2oeP2fuEiOHo6");
                client.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                //byte[] requestBody = Encoding.UTF8.GetBytes(body);
                HttpContent content = new StringContent(body);
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var response = await client.PostAsync(url, content);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON
                await response.Content.ReadAsStringAsync().ContinueWith(t =>
                {
                    if (t.IsCompleted)
                    {
                        requestResult.IsSuccess = true;
                        requestResult.Result = t.Result;
                        callback?.Invoke(requestResult);
                    }
                });
            }
        }
        catch (Exception e)
        {
            if (e.InnerException != null)
                requestResult.Message = e.InnerException.Message;
            else if (e.Message.Contains("已取消一个任务"))
                requestResult.Message = "连接服务器超时,请重试";
            else if (e.Message.Contains("404"))
                requestResult.Message = "连接服务器404,请重试";
            else
                requestResult.Message = e.Message;
            callback?.Invoke(requestResult);
        }
    }
    
    public static async void AsyncGet(string url, Action<RequestResult> callback, int timeoutSeconds = 10)
    {
        var requestResult = new RequestResult();
        if (!IsConnectedInternet())
        {
            requestResult.Message = "网络连接错误,请稍后再试。";
            callback?.Invoke(requestResult);
            return;
        }
    
        try
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("authorization", "LJQfL1A2oeP2fuEiOHo6");
                client.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                var response = await client.GetAsync(url);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON
                await response.Content.ReadAsStringAsync().ContinueWith(t =>
                {
                    if (t.IsCompleted)
                    {
                        requestResult.IsSuccess = true;
                        requestResult.Result = t.Result;
                        callback?.Invoke(requestResult);
                    }
                });
            }
        }
        catch (Exception e)
        {
            if (e.InnerException != null)
                requestResult.Message = e.InnerException.Message;
            else if (e.Message.Contains("已取消一个任务"))
                requestResult.Message = "连接服务器超时,请重试";
            else if (e.Message.Contains("404"))
                requestResult.Message = "连接服务器404,请重试";
            else
                requestResult.Message = e.Message;
            callback?.Invoke(requestResult);
        }
    }
    
    public static async void AsyncPut(string url, string body, Action<RequestResult> callback, int timeoutSeconds = 10)
    {
        var requestResult = new RequestResult();
        if (!IsConnectedInternet())
        {
            requestResult.Message = "网络连接错误,请稍后再试。";
            callback?.Invoke(requestResult);
            return;
        }
    
        try
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("authorization", "LJQfL1A2oeP2fuEiOHo6");
                client.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                HttpContent content = new StringContent(body);
                content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var response = await client.PutAsync(url, content);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON
                await response.Content.ReadAsStringAsync().ContinueWith(t =>
                {
                    if (t.IsCompleted)
                    {
                        requestResult.IsSuccess = true;
                        requestResult.Result = t.Result;
                        callback?.Invoke(requestResult);
                    }
                });
            }
        }
        catch (Exception e)
        {
            if (e.InnerException != null)
                requestResult.Message = e.InnerException.Message;
            else if (e.Message.Contains("已取消一个任务"))
                requestResult.Message = "连接服务器超时,请重试";
            else if (e.Message.Contains("404"))
                requestResult.Message = "连接服务器404,请重试";
            else
                requestResult.Message = e.Message;
            callback?.Invoke(requestResult);
        }
    }
    
    public static async void AsyncDelete(string url, Action<RequestResult> callback, int timeoutSeconds = 10)
    {
        var requestResult = new RequestResult();
        if (!IsConnectedInternet())
        {
            requestResult.Message = "网络连接错误,请稍后再试。";
            callback?.Invoke(requestResult);
            return;
        }
    
        try
        {
            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Add("authorization", "LJQfL1A2oeP2fuEiOHo6");
                client.Timeout = new TimeSpan(0, 0, timeoutSeconds);
                var response = await client.DeleteAsync(url);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON
                await response.Content.ReadAsStringAsync().ContinueWith(t =>
                {
                    if (t.IsCompleted)
                    {
                        requestResult.IsSuccess = true;
                        requestResult.Result = t.Result;
                        callback?.Invoke(requestResult);
                    }
                });
            }
        }
        catch (Exception e)
        {
            if (e.InnerException != null)
                requestResult.Message = e.InnerException.Message;
            else if (e.Message.Contains("已取消一个任务"))
                requestResult.Message = "连接服务器超时,请重试";
            else if (e.Message.Contains("404"))
                requestResult.Message = "连接服务器404,请重试";
            else
                requestResult.Message = e.Message;
            callback?.Invoke(requestResult);
        }
    }

    上面使用到的RequestResult类:

    public class RequestResult : IDisposable
    {
        public bool IsSuccess { get; set; }
    
        public string Result { get; set; }
    
        public string Message { get; set; }
    
        public RequestResult(bool isSuccess = false, string result = "", string message = "")
        {
            IsSuccess = isSuccess;
            Result = result;
            Message = message;
        }
    
        ~RequestResult()
        {
            Dispose();
        }
    
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);//不需要再调用本对象的Finalize方法
        }
    
        protected virtual void Dispose(Boolean disposing)
        {
            if (disposing)
            {
                //--- 清理托管资源 ---//
            }
    
            //--- 清理非托管资源 ---//
        }
    }

    还有一个判断Windows系统网络连接状态的方法:

    #region 网络状态测试
    
    [DllImport("winInet.dll")]
    private static extern bool InternetGetConnectedState(ref int dwFlag, int dwReserved);
    
    /// <summary>
    /// 用于检查网络是否可以连接互联网,true表示连接成功,false表示连接失败 
    /// </summary>
    /// <returns></returns>
    private static bool IsConnectedInternet()
    {
        int description = 0;
        return InternetGetConnectedState(ref description, 0);
    }
    
    #endregion

    最后是使用WebClient进行文件下载,这里使用了Task异步方式,也可以改为普通方法或静态方法:

    /// <summary>
    /// 下载文件
    /// </summary>
    /// <param name="fileUrl">文件地址</param>
    /// <param name="filePath">文件的本地路径</param>
    /// <returns>文件在本地的存储路径</returns>
    private Task GetFileLocalPath(string fileUrl, string filePath)
    {
        return Task.Run(() =>
        {
            try
            {
                using (var mc = new WebClient())
                {
                    mc.DownloadFile(new Uri(fileUrl), filePath);
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorLog("下载文件时出现异常。", ex);
            }
        });
    }
    
    /// <summary>
    /// 下载文件
    /// </summary>
    /// <param name="fileUrl">文件地址</param>
    /// <param name="filePath">文件的本地路径</param>
    /// <returns>文件在本地的存储路径</returns>
    private Task DownloadFile(string fileUrl, string filePath)
    {
        return Task.Run(() =>
        {
            try
            {
                using (var webClient = new WebClient())
                {
                    var netStream = webClient.OpenRead(fileUrl);
                    if (netStream != null)
                    {
                        FileStream fstr = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write);
                        byte[] readbyte = new byte[102400];
                        int realReadLen = netStream.Read(readbyte, 0, readbyte.Length);
                        while (realReadLen > 0)
                        {
                            fstr.Write(readbyte, 0, realReadLen);
                            realReadLen = netStream.Read(readbyte, 0, readbyte.Length);
                            Thread.Sleep(10);
                        }
                        netStream.Dispose();
                        fstr.Flush();
                        fstr.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteErrorLog("下载文件时出现异常。", ex);
            }
        });
    }

    以上,有需要的可以拿去使用,通用性还是能保证的,有特殊用途改改就可以了,比如微信公众平台上传文件时form-data内的name是media。

  • 相关阅读:
    Asp.NET 4.0 ajax实例DataView 模板编程1
    ASP.NET 4.0 Ajax 实例DataView模板编程 DEMO 下载
    部分东北话、北京话
    .NET 培训课程解析(一)
    ASP.NET 4.0 Ajax 实例DataView模板编程2
    ASP.NET Web Game 架构设计1服务器基本结构
    ASP.NET Web Game 构架设计2数据库设计
    TFS2008 基本安装
    Linux上Oracle 11g安装步骤图解
    plsql developer远程连接oracle数据库
  • 原文地址:https://www.cnblogs.com/lgx5/p/9446763.html
Copyright © 2011-2022 走看看