C#开发WinForm之Http请求

12 篇文章 6 订阅

C#开发WinForm之Http请求

前言

HTTP请求是常见的web开发请求,简历也容易上手,当然对于 前端来说,jsweb的http很熟悉,而换种语言的c#是怎样的呢?

Newtonsoft.Json是一个处理json格式的c#库,我们可以去下载它并学习使用它。

http请求工具库里

我的工具库里使用了HttpClient

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Security;


using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Xml.Serialization;
using DongliCAD.utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using Bricscad.ApplicationServices;
using Bricscad.EditorInput;
using DongliCAD.common;

namespace DongliCAD.utils
{
    class HttpUtil
    {
       
        /// <summary>
        /// get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static JObject GetResponse(string url)
        {
            try
            {
                if (string.IsNullOrEmpty(url))
                {
                    throw new ArgumentNullException("url");
                }
                if (url.StartsWith("https"))
                    System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

                HttpClient httpClient = new HttpClient();
                httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                if (GlobalData.Authorization.Length > 0)
                {
                    httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
                }
                HttpResponseMessage response = httpClient.GetAsync(url).Result;
                StatusCodeHandler(response);
                if (response.IsSuccessStatusCode)
                {
                    string result = response.Content.ReadAsStringAsync().Result;
                    JObject jo = (JObject)JsonConvert.DeserializeObject(result);
                    return jo;
                }
            }
            catch(Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if(msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return new JObject();
        }

        public static T GetResponse<T>(string url)
              where T : class, new()
        {
            T result = default(T);
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));
            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try { 
                HttpResponseMessage response = httpClient.GetAsync(url).Result;
                StatusCodeHandler(response);
                
                if (response.IsSuccessStatusCode)
                {
                    Task<string> t = response.Content.ReadAsStringAsync();
                    string s = t.Result;
                    result = JsonConvert.DeserializeObject<T>(s);
                }
            }
            catch(Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if(msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return result;
        }

        /// <summary>
        /// post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">post数据</param>
        /// <returns></returns>
        public static JObject PostResponse(string url, string postData)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpContent httpContent = new StringContent(postData);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            HttpClient httpClient = new HttpClient();
            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try {
                HttpResponseMessage response = httpClient.PostAsync(url, httpContent).Result;
                StatusCodeHandler(response);
                AuthorizationHandler(response, url);
                if (response.IsSuccessStatusCode)
                {
                    string result = response.Content.ReadAsStringAsync().Result;
                    JObject jo = (JObject)JsonConvert.DeserializeObject(result);
                    return jo;
                }
            }
            catch (Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if (msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return new JObject();
        }

        private static Boolean StatusCodeHandler(HttpResponseMessage response)
        {
            Boolean ct = true;
            String statusCode = response.StatusCode.ToString();
            string result = response.Content.ReadAsStringAsync().Result;
            JObject jo = (JObject)JsonConvert.DeserializeObject(result);
            if (statusCode == HttpStatusCode.Unauthorized.ToString())
            {
                AlertUtil.Show("请重新登陆");
                LoginForm login = new LoginForm();
                login.ShowDialog();
            } else if (statusCode == HttpStatusCode.Forbidden.ToString())
            {
                AlertUtil.Show("禁止访问" + jo["data"]["msg"]);
            }
            else if (statusCode == HttpStatusCode.NotFound.ToString())
            {
                AlertUtil.Show("请求失败");
            }else if(statusCode == HttpStatusCode.BadRequest.ToString())
            {
                AlertUtil.Show("400");
            }

            return ct;
        }

        private static void AuthorizationHandler(HttpResponseMessage response, string url)
        {
            Regex reg = new Regex("(.+)/login$");
            Boolean isLogin = reg.IsMatch(url);
            if (isLogin)
            {
                GlobalData.Authorization = getHeaderByKey(response, "Authorization");
            }
        }

        private static string getHeaderByKey(HttpResponseMessage response, string key)
        {
            string result = "";
            string header = response.Headers.ToString();
            string[] headers = header.Split("\r\n".ToCharArray());
            if(headers.Count() > 0)
            {
                foreach (string item in headers)
                {
                    Regex reg = new Regex("^"  + key + ":(.+)");
                    if (reg.IsMatch(item))
                    {
                        string[] tokens = item.Split(':');
                        if (tokens[0].ToString() == key)
                        {
                            result = tokens[1].ToString();
                            break;
                        }
                    }
                    else
                    {
                        reg = new Regex("^" + key + "=(.+)");
                        if (reg.IsMatch(item))
                        {
                            string[] tokens = item.Split('=');
                            if (tokens[0].ToString() == key)
                            {
                                result = tokens[1].ToString();
                                break;
                            }
                        }
                    }
                }

            }
            return result;
        }

        /// <summary>
        /// 发起post请求
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="url">url</param>
        /// <param name="postData">post数据</param>
        /// <returns></returns>
        public static T PostResponse<T>(string url, string postData)
           where T : class, new()
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpContent httpContent = new StringContent(postData);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            HttpClient httpClient = new HttpClient();

            T result = default(T);
            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try
            {
                HttpResponseMessage response = httpClient.PostAsync(url, httpContent).Result;
                StatusCodeHandler(response);
                if (response.IsSuccessStatusCode)
                {
                    Task<string> t = response.Content.ReadAsStringAsync();
                    string s = t.Result;

                    result = JsonConvert.DeserializeObject<T>(s);
                }
            }
            catch (Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if (msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return result;
        }


        /// <summary>
        /// put请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="putData">put数据</param>
        /// <returns></returns>
        public static JObject PutResponse(string url, string putData = "")
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpContent httpContent = new StringContent(putData);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            HttpClient httpClient = new HttpClient();
            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try
            {
                HttpResponseMessage response = httpClient.PutAsync(url, httpContent).Result;
                StatusCodeHandler(response);
                if (response.IsSuccessStatusCode)
                {
                    string result = response.Content.ReadAsStringAsync().Result;
                    JObject jo = (JObject)JsonConvert.DeserializeObject(result);
                    return jo;
                }
            }
            catch (Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if (msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return new JObject();
        }

        /// <summary>
        /// delete请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static JObject DeleteResponse(string url)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try
            {
                HttpResponseMessage response = httpClient.DeleteAsync(url).Result;
                StatusCodeHandler(response);
                string statusCode = response.StatusCode.ToString();
                if (response.IsSuccessStatusCode)
                {
                    string result = response.Content.ReadAsStringAsync().Result;

                    JObject jo = (JObject)JsonConvert.DeserializeObject(result);
                    return jo;
                }
            }
            catch (Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if (msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return new JObject();
        }

        private static void exceptionHandler(string msg)
        {
            throw new DyConnectException(msg);
        }
    }
}

其中

	if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }

是我登陆成功后返回的token,我把token放在header放在头部传给后台,如果具体业务不一样,可以修改。
使用try…catch当连接后台不成功时抛出异常。
DyConnectException是我自定义的一个异常类,用于处理连接后台不成功时的异常。
DyConnectException.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DongliCAD
{
    class DyConnectException : Exception
    {
        public int status = 911;
        public string message;
        public DyConnectException(string message)
        {
            this.message = message;
        }
    }
}

其中Get和Post我提供了2种方式请求,一个是返回json格式的字段串,一个是解析成对象。

使用方法

Get请求

  1. 返回json格式字符串,这个字符串解析成JObject对象,(JObject是Newtonsoft.Json里对象)
 JObject jObject = HttpUtil.GetResponse("请求的url地址");

取数据方式:jObject["code"].ToString()jObject["code"]["code1"].ToString()

  1. 返回对象
 ItemTypeRootVo itemTypeRootVo = HttpUtil.GetResponse<ItemTypeRootVo>("请求的url地址");

ItemTypeRootVo是我自定义的对象,比如如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DongliCAD.vo
{
    public class ItemTypeRootVo
    {
        /// <summary>
        /// 
        /// </summary>
        public int code { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public string msg { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public int error { get; set; }

        /// <summary>
        /// 
        /// </summary>
        public List<ItemTypeVo> data { get; set; }
    }

    public class ItemTypeVo
    {
        /// <summary>
        /// 
        /// </summary>
        public string uid { get; set; }
        /// <summary>
        /// 总装图
        /// </summary>
        public string itemTypeName { get; set; }
        /// <summary>
        /// 类型
        /// </summary>
        public string userTitle1 { get; set; }
        /// <summary>
        /// 中心高
        /// </summary>
        public string userTitle2 { get; set; }
        /// <summary>
        /// 总中心距
        /// </summary>
        public string userTitle3 { get; set; }
        /// <summary>
        /// 级数
        /// </summary>
        public string userTitle4 { get; set; }
        /// <summary>
        /// 输入轴轴径
        /// </summary>
        public string userTitle5 { get; set; }
        /// <summary>
        /// 输出轴轴径
        /// </summary>
        public string userTitle6 { get; set; }
        /// <summary>
        /// 输出力矩
        /// </summary>
        public string userTitle7 { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public string userTitle8 { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public int order { get; set; }
    }
}

那么在请求成功后,会自动把json数据解析成ItemTypeRootVo对象,相对来说更方便些。

Post请求

  1. 返回字符串请求,这种请求的get类似,同时post需要向后台传递数据。使用JObjectJArray
    比如传递对象
 	    JObject jObj = new JObject();
            jObj.Add(new JProperty("userId", userName));
            jObj.Add(new JProperty("password", password));
            JObject result = HttpUtil.PostResponse("请求的url地址", jObj.ToString());

或者传递数组

	    JObject jObj = new JObject();
            JArray jArray = new JArray();
            jObj.Add(new JProperty("uid", workspaceCadInfoVo.itemRevUid));
            jObj.Add(new JProperty("ctype", "ITEMREVISION"));
            jArray.Add(jObj);
            JObject result = HttpUtil.PostResponse("请求的url地址", jArray.ToString());
  1. 返回对象,同get一样。

扩展

文件上传

有时候我们需要上传文件,同时也上传数据。方法如下,以异步方式上传

/// <summary>
        /// post请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="postData">post数据</param>
        /// <returns></returns>
        public static JObject PostFileResponse(string url, MultipartFormDataContent postData)
        {
            if (string.IsNullOrEmpty(url))
            {
                throw new ArgumentNullException("url");
            }
            if (url.StartsWith("https"))
                System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            //HttpContent httpContent = new FormCo StringContent(postData);
            //postData.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            HttpClient httpClient = new HttpClient();
            if (GlobalData.Authorization.Length > 0)
            {
                httpClient.DefaultRequestHeaders.Add("Authorization", GlobalData.Authorization);
            }
            try
            {
                HttpResponseMessage response = httpClient.PostAsync(url, postData).Result;
                StatusCodeHandler(response);
                AuthorizationHandler(response, url);
                if (response.IsSuccessStatusCode)
                {
                    string result = response.Content.ReadAsStringAsync().Result;
                    JObject jo = (JObject)JsonConvert.DeserializeObject(result);
                    return jo;
                }
            }
            catch (Exception e)
            {
                string msg = e.InnerException.InnerException.Message;
                if (msg == "无法连接到远程服务器")
                {
                    AlertUtil.Show("服务器无响应,请重新配置环境");
                    exceptionHandler("连接失败");
                }
            }
            return new JObject();
        }

使用方式

	    MultipartFormDataContent dataContent = new MultipartFormDataContent();
		
	    //传文件
            string pdfFileName = "test.pdf";
            FileStream pdfFsRead = new FileStream("D:/test/" + pdfFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            byte[] pdfBytes = new byte[(int)pdfFsRead.Length];
            pdfFsRead.Read(pdfBytes, 0, pdfBytes.Length);
            //ByteArrayContent pdfArrayContent = new ByteArrayContent(File.ReadAllBytes("D:/test/" + pdfFileName));
            ByteArrayContent pdfArrayContent = new ByteArrayContent(pdfBytes);
            pdfArrayContent.Headers.Add("Content-Type", "multipart/form-data");
            dataContent.Add(pdfArrayContent, "files", pdfFileName);

		//传数据,注意格式是value-key,不是key-value
 	     dataContent.Add(new StringContent("123"), "itemRevisionUid");
            dataContent.Add("456", "datasetUid");
		
		//请求接口
	   JObject jObject = HttpUtil.PostFileResponse("请求的url地址", dataContent);

上面将文件和数据都放到MultipartFormDataContent对象里.
后台接口类似如下(使用kotlin语法写的。和java差不多)

	/**
     * 保存图纸和pdf文档
     */
    @PostMapping("/saveDrawingno")
    fun saveDrawingno(
                      @RequestParam itemRevisionUid:Long,@RequestParam datasetUid: Long,
                      @RequestParam files: Array<MultipartFile>): ResponseEntity<Any> {
       
        //逻辑部分
    }

实现了即上传文件又上传数据的功能。

文件下载

文件下载包括同步下载和异常下载。
工具类HttpDownUtil.cs如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Security;


using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Xml.Serialization;
using DongliCAD.utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Collections.Specialized;

namespace DongliCAD.utils
{
    class HttpDownUtil
    {
        /**********************************************上传***************************************************************************/
        public static void SetHeaderValue(WebHeaderCollection header, string name, string value)
        {
            var property = typeof(WebHeaderCollection).GetProperty("InnerCollection",
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            if (property != null)
            {
                var collection = property.GetValue(header, null) as NameValueCollection;
                collection[name] = value;
            }
        }

        /**********************************************下载***************************************************************************/
        /********************同步下载***************************/
        /// <summary>
        /// 同步下载
        /// Http下载文件
        /// </summary>
        public static string HttpDownloadFile(string url, string path)
        {
            // 设置参数
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            if (GlobalData.Authorization.Length > 0)
            {
                request.Headers.Add("Authorization", GlobalData.Authorization);
            }
            //发送请求并获取相应回应数据
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            //直到request.GetResponse()程序才开始向目标网页发送Post请求
            Stream responseStream = response.GetResponseStream();
            //创建本地文件写入流
            Stream stream = new FileStream(path, FileMode.Create);
            byte[] bArr = new byte[1024];
            int size = responseStream.Read(bArr, 0, (int)bArr.Length);
            while (size > 0)
            {
                stream.Write(bArr, 0, size);
                size = responseStream.Read(bArr, 0, (int)bArr.Length);
            }
            stream.Close();
            responseStream.Close();
            return path;
        }


        /********************异步下载***************************/
        /// <summary>
        /// 异步回调
        /// </summary>
        /// <param name="result">Result.</param>
        private static void BeginResponseCallback(IAsyncResult result)
        {
            DownloadTmp downloadInfo = (DownloadTmp)result.AsyncState;
            HttpWebRequest Request = downloadInfo.webRequest;
            HttpWebResponse Response = (HttpWebResponse)Request.EndGetResponse(result);
            
            if (Response.StatusCode == HttpStatusCode.OK || Response.StatusCode == HttpStatusCode.Created)
            {
                string filePath = downloadInfo.filePath;


                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                }
                //FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write);
                FileStream fs = File.OpenWrite(filePath);

                Stream stream = Response.GetResponseStream();

                int count = 0;
                int num = 0;
                if (Response.ContentLength > 0)
                {
                    downloadInfo.AllContentLength = Response.ContentLength;
                    var buffer = new byte[2048 * 100];
                    do
                    {
                        num++;
                        count = stream.Read(buffer, 0, buffer.Length);
                        downloadInfo.currentContentLength = num * buffer.Length;
                        fs.Write(buffer, 0, count);
                        if (downloadInfo.loadingCallback != null)
                        {
                            float pro = (float)fs.Length / Response.ContentLength * 100;
                            downloadInfo.loadingCallback((int)pro);
                        }
                    } while (count > 0);
                }
                fs.Close();
                Response.Close();
                if (downloadInfo.succeedCallback != null)
                {
                    downloadInfo.succeedCallback();
                }
            }
            else
            {
                Response.Close();
                if (downloadInfo.failedCallback != null)
                {
                    downloadInfo.failedCallback();
                }
            }
        }

        /// <summary>
        /// 下载文件,异步
        /// </summary>
        /// <param name="URL">下载路径</param>
        /// <param name="downloadPath">文件下载路径</param>
        /// <returns></returns>
        public static void HttpDownloadFileAsyn(string URL, ref DownloadTmp downloadInfo)
        {
            HttpWebRequest Request = (HttpWebRequest)WebRequest.Create(URL);
            downloadInfo.webRequest = Request;
            Request.BeginGetResponse(BeginResponseCallback, downloadInfo);
        }
    }

    /// <summary>
    /// 下载请求信息
    /// </summary>
    public class DownloadTmp
    {
        /// <summary>
        /// 文件名
        /// </summary>
        public string fileName;
        /// <summary>
        /// 下载路径
        /// </summary>
        public string filePath;
        /// <summary>
        /// 下载进度回调
        /// </summary>
        public Action<int> loadingCallback;
        /// <summary>
        /// 完成回调
        /// </summary>
        public Action succeedCallback;
        /// <summary>
        /// 失败回调
        /// </summary>
        public Action failedCallback;
        /// <summary>
        /// webRequest
        /// </summary>
        public HttpWebRequest webRequest;

        public long AllContentLength;

        public long currentContentLength;
    }
}

同步下载:HttpDownloadFile()
异步下载:HttpDownloadFileAsyn()

使用方式也很简单

 	    DownloadTmp downloadTmp = new DownloadTmp();
            downloadTmp.filePath = @“D:\test\666.txt”;
            HttpDownloadZip(downUrl, ref downloadTmp);

其中在外部我们也可以访问downloadTmp里的参数。谁让它用ref修饰呢

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值