HTTP网络请求的一些知识点

名词解释

Accept:

发送端(客户端)希望接受的数据类型。

比如:
text/xml(application/json)代表客户端希望接受的数据类型是xml(json )类型

Content-Type:

发送端(客户端|服务器)发送的实体数据的数据类型。

比如:
text/html(application/json)代表发送端发送的数据格式是html(json)。
二者合起来,Accept:text/xml;Content-Type:text/html即代表希望接受的数据类型是xml格式,本次请求发送的数据的数据格式是html。

Conteny-Type:内容类型,即请求/响应的内容区数据的媒体类型
Accept:用来指定什么媒体类型的响应是可接受的,即告诉服务器我需要什么媒体类型的数据,此时服务器应该根据Accept请求头生产指定媒体类型的数据。

Content-Type(内容类型)

一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。

Content-Type 标头告诉客户端实际返回的内容的内容类型。

语法格式:

Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something

HTTP协议传输的媒体类型及如何表示媒体类型

MediaType

即是Internet Media Type,互联网媒体类型;也叫做MIME类型,在Http协议消息头中,使用Content-Type来表示具体请求中的媒体类型信息。

类型格式:type/subtype(;parameter)? type
主类型,任意的字符串,如text,如果是号代表所有;
subtype 子类型,任意的字符串,如html,如果是号代表所有;
parameter 可选,一些参数,如Accept请求头的q参数, Content-Type的 charset参数。
例如:Content-Type: text/html;charset:utf-8;

常见的媒体格式类型如下:

常见的MediaType:

  1. text/html:HTML格式
  2. text/plain:纯文本格式
  3. text/xml: XML格式
  4. image/gif:gif图片格式
  5. image/jpeg:jpg图片格式
  6. image/png:png图片格式
  7. application/xhtml+xml:XHTML格式
  8. application/xml: XML数据格式
  9. application/atom+xml:Atom XML聚合格式
  10. application/json:JSON数据格式
  11. application/pdf:pdf格式
  12. application/msword:Word文档格式
  13. application/octet-stream: 二进制流数据(如常见的文件下载)
  14. application/x-www-form-urlencoded:中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
  15. multipart/form-data: 需要在表单中进行文件上传时,就需要使用该格式

一些示例

Conteny-Type:内容类型,即请求/响应的内容区数据的媒体类型
Accept:用来指定什么媒体类型的响应是可接受的,即告诉服务器我需要什么媒体类型的数据,此时服务器应该根据Accept请求头生产指定媒体类型的数据。
问题:

服务器端可以通过指定【headers = “Content-Type=application/json”】来声明可处理(可消费)的媒体类型,即只消费Content-Type指定的请求内容体数据;
客户端如何告诉服务器端它只消费什么媒体类型的数据呢?即客户端接受(需要)什么类型的数据呢?服务器应该生产什么类型的数据?此时我们可以请求的Accept请求头来实现这个功能。

@RequestMapping(value = "/response/ContentType", headers = "Accept=application/json")
public void response2(HttpServletResponse response) throws IOException {
    //表示响应的内容区数据的媒体类型为json格式,且编码为utf-8(客户端应该以utf-8解码)
    response.setContentType("application/json;charset=utf-8");
    //写出响应体内容
    String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";
    response.getWriter().write(jsonData);
}
@Controller    
@RequestMapping(value = "/users", method = RequestMethod.POST, consumes="application/json", produces="application/json")    
@ResponseBody  
public List<User> addUser(@RequestBody User userl) {        
    // implementation omitted    
    return List<User> users;  
}

上面两个例子都表示了request请求中Accept头中包含了"application/json"的请求,同时暗示了返回的内容类型为application/json:

  1. produces标识:produces=“application/json”
  2. headers =“Accept=application/json”

其中request Content-Type为“application/json”类型的请求.

当你有如下Accept头,将遵守如下规则进行应用:

  1. Accept:text/html,application/xml,application/json
    将按照如下顺序进行produces的匹配 ①text/html ②application/xml ③application/json

  2. Accept:application/xml;q=0.5,application/json;q=0.9,text/html
    将按照如下顺序进行produces的匹配 ①text/html ②application/json ③application/xml
    参数为媒体类型的质量因子,越大则优先权越高(从0到1)

  3. Accept:/,text/,text/html
    将按照如下顺序进行produces的匹配 ①text/html ②text/
    ③/

即匹配规则为:最明确的优先匹配。

formdata和json的区别

超链接中有图示了这两者的区别,比较完善

Spring MVC中关于关于Content-Type类型信息的使用

这个在https://www.jianshu.com/p/75e560d287f7这个链接中有,没有仔细看,可以之后再看。

http请求的代码编写

目前使用的代码



        private void button4_Click(object sender, EventArgs e)
        {
            HttpPostFileRequestClient test1 = new HttpPostFileRequestClient();
            string fileUrl = "truck_2.jpg";
            FileStream fs = new FileStream("F:\\all_truck\\truck_3.jpg", FileMode.Open, FileAccess.Read);
            test1.SetField("file", "truck_3.jpg", "multipart/form-data", fs);
            

            HttpWebResponse response = test1.Post("http://127.0.0.1:5000/measure/");
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
            string retString = myStreamReader.ReadToEnd();
            MessageBox.Show(retString);
            System.Diagnostics.Debug.WriteLine(retString);

            //这个需要引入Newtonsoft.Json这个DLL并using
            //传入我们的实体类还有需要解析的JSON字符串这样就OK了。然后就可以通过实体类使用数据了。
            Root rt = JsonConvert.DeserializeObject<Root>(retString);

            //这样就可以取出json数据里面的值
            int truck_hgight = rt.truck.height;


            MessageBox.Show("code=" + rt.code + "\r\n" + "costTime=" + rt.costTime+"GIGHT"+ truck_hgight);
            //由于这个JSON字符串的 public List<DataItem> data 是一个集合,所以我们需要遍历集合里面的所有数据

        }

 /// <summary>
    /// 用于以 POST 方式向目标地址提交表单数据, 仅适用于包含文件的请求
    /// </summary>
    public sealed class HttpPostFileRequestClient
    {
        #region - Private -
        private string _boundary;
        private List<byte[]> _postDatas;
        #endregion

        /// <summary>
        /// 获取或设置数据字符编码, 默认使用<see cref="System.Text.Encoding.UTF8"/>
        /// </summary>
        public Encoding Encoding { get; set; } = Encoding.UTF8;

        /// <summary>
        /// 获取或设置 UserAgent
        /// </summary>
        public string UserAgent { get; set; } = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36";

        /// <summary>
        /// 获取或设置 Accept
        /// </summary>
        //public string Accept { get; set; } = "*/*";
        public string Accept { get; set; } = "application/json";

        /// <summary>
        /// 获取或设置 Referer
        /// </summary>
        public string Referer { get; set; }

        /// <summary>
        /// 获取或设置 Cookie 容器
        /// </summary>
        public CookieContainer CookieContainer { get; set; } = new CookieContainer();

        /// <summary>
        /// 初始化一个用于以 POST 方式向目标地址提交表单数据的<see cref="HttpPostFileRequestClient"/>实例
        /// </summary>
        public HttpPostFileRequestClient()
        {
            this._boundary = DateTime.Now.Ticks.ToString("X");
            this._postDatas = new List<byte[]>();
        }

        /// <summary>
        /// 设置表单数据字段, 用于存放文本类型数据
        /// </summary>
        /// <param name="fieldName">指定的字段名称</param>
        /// <param name="fieldValue">指定的字段值</param>
        public void SetField(string fieldName, string fieldValue)
        {
            var field = $"--{this._boundary}\r\n" +
                        $"Content-Disposition: form-data;name=\"{fieldName}\"\r\n\r\n" +
                        $"{fieldValue}\r\n";
            this._postDatas.Add(this.Encoding.GetBytes(field));
        }

        /// <summary>
        /// 设置表单数据字段, 用于文件类型数据
        /// </summary>
        /// <param name="fieldName">字段名称</param>   应该是表格某一列的名称
        /// <param name="fileName">文件名</param>
        /// <param name="contentType">内容类型, 传入 null 将默认使用 application/octet-stream</param>
        /// <param name="fs">文件流</param>
        public void SetField(string fieldName, string fileName, string contentType, Stream fs)
        {
            var fileBytes = new byte[fs.Length];
            using (fs)
            {
                fs.Read(fileBytes, 0, fileBytes.Length);
            }
            SetField(fieldName, fileName, contentType, fileBytes);
        }

        /// <summary>
        /// 设置表单数据字段, 用于文件类型数据
        /// </summary>
        /// <param name="fieldName">字段名称</param>
        /// <param name="fileName">文件名</param>
        /// <param name="contentType">内容类型, 传入 null 将默认使用 application/octet-stream</param>
        /// <param name="fileBytes">文件字节数组</param>
        public void SetField(string fieldName, string fileName, string contentType, byte[] fileBytes)
        {
            var field = $"--{this._boundary}\r\n" +
                        $"Content-Disposition: form-data; name=\"{fieldName}\";filename=\"{fileName}\"\r\n" +
                        $"Content-Type:{contentType ?? "application/octet-stream"}\r\n\r\n";
            this._postDatas.Add(this.Encoding.GetBytes(field));
            this._postDatas.Add(fileBytes);
            this._postDatas.Add(this.Encoding.GetBytes("\r\n"));
        }

        /// <summary>
        /// 以POST方式向目标地址提交表单数据
        /// </summary>
        /// <param name="url">目标地址, http(s)://sample.com</param>
        /// <returns>目标地址的响应</returns>
        public HttpWebResponse Post(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
                throw new ArgumentNullException(nameof(url));

            HttpWebRequest request = null;
            if (url.ToLowerInvariant().StartsWith("https"))
            {
                request = WebRequest.Create(url) as HttpWebRequest;
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((s, c, ch, ss) => { return true; });
                request.ProtocolVersion = HttpVersion.Version11;
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                request.KeepAlive = true;
                ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.DefaultConnectionLimit = 100;
                ServicePointManager.Expect100Continue = false;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }


            request.Method = "POST";
            request.ContentType = "multipart/form-data;boundary=" + _boundary;
            request.UserAgent = this.UserAgent;
            request.Accept = this.Accept;
            request.Referer = this.Referer;
            request.CookieContainer = this.CookieContainer;


            var end = $"--{this._boundary}--\r\n";
            Type end_Name = end.GetType();
            Console.WriteLine("变量end的类型是{0}",
                end_Name.ToString());

            //不自动关闭控制台,等待输入
            Console.ReadLine();

            this._postDatas.Add(this.Encoding.GetBytes(end));

            var requestStream = request.GetRequestStream();

            //StreamReader myStreamReader = new StreamReader(requestStream, Encoding.UTF8);
            //string retString = myStreamReader.ReadToEnd();
            //MessageBox.Show(retString);


            //Type requestStream_Name = requestStream.GetType();
            //Console.WriteLine("变量end的类型是{0}",
            //    requestStream_Name.ToString());
            

            

            foreach (var item in this._postDatas)
            {
                requestStream.Write(item, 0, item.Length);
            }
            return request.GetResponse() as HttpWebResponse;
        }

        /// <summary>
        /// 以POST方式向目标地址提交表单数据
        /// </summary>
        /// <param name="url">目标地址, http(s)://sample.com</param>
        /// <returns>目标地址的响应</returns>
        public async Task<HttpWebResponse> PostAsync(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
                throw new ArgumentNullException(nameof(url));

            HttpWebRequest request = null;
            if (url.ToLowerInvariant().StartsWith("https"))
            {
                request = WebRequest.Create(url) as HttpWebRequest;
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback((s, c, ch, ss) => { return true; });
                request.ProtocolVersion = HttpVersion.Version11;
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                request.KeepAlive = true;
                ServicePointManager.CheckCertificateRevocationList = true; ServicePointManager.DefaultConnectionLimit = 100;
                ServicePointManager.Expect100Continue = false;
            }
            else
            {
                request = WebRequest.Create(url) as HttpWebRequest;
            }

            request.Method = "POST";
            request.ContentType = "multipart/form-data;boundary=" + _boundary;
            request.UserAgent = this.UserAgent;
            request.Accept = this.Accept;
            request.Referer = this.Referer;
            request.CookieContainer = this.CookieContainer;

            var end = $"--{this._boundary}--\r\n";
            Type end_Name = end.GetType();
            Console.WriteLine("变量end的类型是{0}",
                end_Name.ToString());

            //不自动关闭控制台,等待输入
            Console.ReadLine();


            this._postDatas.Add(this.Encoding.GetBytes(end));

            var requestStream = await request.GetRequestStreamAsync();
            Type requestStream_Name = requestStream.GetType();
            Console.WriteLine("变量end的类型是{0}",
                requestStream_Name.ToString());

            foreach (var item in this._postDatas)
            {
                await requestStream.WriteAsync(item, 0, item.Length);
            }
            return await request.GetResponseAsync() as HttpWebResponse;
        }
   }

一些比较好的链接

Http请求中Accept、Content-Type讲解以及在Spring MVC中的应用
这个链接非常清楚明白,也有一些参考代码

C# 模拟 HTTP POST请求
这个链接中有两个代码
第一个:用于以 POST 方式向目标地址提交表达数据,application/x-www-form-urlencoded 编码方式:这个没使用
第二个:用于以 POST 方式向目标地址提交表单数据, 仅适用于包含文件的请求,multipart/form-data;
第二个代码我们经过测试可以使用,就是我上面贴出的代码。

C#中HttpClient使用注意:预热与长连接
这篇博文写出了如何让服务器和客服端保持持续连接,减少耗时。

C#网络编程之Http请求
这篇博客写出了客户端:application/json接收,multipart/form-data发送
服务器端接受的代码

C# 网络请求
写了接口,不写程序调用可以是使用postman 发包看看情况,简单写了HttpClient,HttpWebRequest的post和get请求方式,写的还是比较简洁。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值