什么是 HTTP ?
超文本传输协议(HTTP)的设计目的是保证客户端与服务器之间的通信。
HTTP 的工作方式是客户端与服务器之间的请求-应答协议。
web 浏览器可能是客户端,而计算机上的网络应用程序也可能作为服务器端。
举例:客户端(浏览器)向服务器提交 HTTP 请求;服务器向客户端返回响应。响应包含关于请求的状态信息以及可能被请求的内容。
两种最常用的 HTTP 方法是:GET 和 POST。
-
GET - 从指定的资源请求数据。
-
POST - 向指定的资源提交要被处理的数据。
一. GET请求
参数是通过Url来传输,接在Url后面中间用?分开,不同参数之间用&分开,也可不带参数,直接从服务器拉取数据。
-
GET 请求可被缓存
-
GET 请求保留在浏览器历史记录中
-
GET 请求可被收藏为书签
-
GET 请求不应在处理敏感数据时使用
-
GET 请求有长度限制
-
GET 请求只应当用于取回数据
1 string result = String.Empty; 2 string url = $"http://localhost:52307/API/CommonAPI/GetTest1?param1={100}¶m2={200}"; 3 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 4 request.Method = "GET"; 5 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 6 Stream stream = response.GetResponseStream(); 7 if (stream != null) 8 { 9 using (StreamReader reader = new StreamReader(stream, Encoding.Default)) 10 { 11 result = reader.ReadToEnd(); 12 reader.Close(); 13 } 14 } 15 16 Console.WriteLine($"result={result}"); 17 Console.ReadKey();
二. POST请求
请注意,查询字符串(名称/值对)是在 POST 请求的 HTTP 消息主体中发送的。
-
POST 请求不会被缓存
-
POST 请求不会保留在浏览器历史记录中
-
POST 不能被收藏为书签
-
POST 请求对数据长度没有要求
1. ContentType = "application/x-www-form-urlencoded"
1 string result = String.Empty; 2 3 string data = $"param1={100}¶m2={200}"; 4 byte[] bytes = Encoding.Default.GetBytes(data); 5 6 string url = $"http://localhost:52307/API/CommonAPI/PostTest2"; 7 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 8 request.Method = "POST"; 9 request.ContentType = "application/x-www-form-urlencoded"; 10 request.ContentLength = bytes.Length; 11 Stream requestStream = request.GetRequestStream(); 12 requestStream.Write(bytes, 0, bytes.Length); 13 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 14 Stream responseStream = response.GetResponseStream(); 15 if (responseStream != null) 16 { 17 using (StreamReader reader = new StreamReader(responseStream, Encoding.Default)) 18 { 19 result = reader.ReadToEnd(); 20 reader.Close(); 21 } 22 } 23 24 Console.WriteLine($"result={result}"); 25 Console.ReadKey();
WebApi 获取请求参数:
1 try 2 { 3 HttpContextBase httpContextBase = (HttpContextBase)Request.Properties["MS_HttpContext"]; 4 HttpRequestBase httpRequestBase = httpContextBase.Request; 5 6 string param1 = httpRequestBase.Form["param1"]; 7 string param2 = httpRequestBase.Form["param2"]; 8 PrintLog.WriteLog(LogType.DEBUG, "CommonAPIController", "PostTest2", $"param1={param1},param2={param2}"); 9 10 return JsonConvert.SerializeObject(new { param1, param2 }); 11 } 12 catch (Exception) 13 { 14 15 throw; 16 }
1 public string PostTest1([FromBody]AClass p) 2 { 3 try 4 { 5 PrintLog.WriteLog(LogType.DEBUG, "CommonAPIController", "PostTest1", $"param1={p.Param1},param2={p.Param2}"); 6 7 return JsonConvert.SerializeObject(new { p.Param1, p.Param2 }); 8 } 9 catch (Exception) 10 { 11 12 throw; 13 } 14 } 15 public class AClass 16 { 17 public string Param1 { get; set; } 18 public string Param2 { get; set; } 19 }
2. ContentType = "application/json"
1 string result = String.Empty; 2 3 string data = "{"param1":100,"param2":200}"; 4 byte[] bytes = Encoding.Default.GetBytes(data); 5 6 string url = $"http://localhost:52307/API/CommonAPI/PostTest1"; 7 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 8 request.Method = "POST"; 9 request.ContentType = "application/json"; 10 request.ContentLength = bytes.Length; 11 Stream requestStream = request.GetRequestStream(); 12 requestStream.Write(bytes, 0, bytes.Length); 13 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 14 Stream responseStream = response.GetResponseStream(); 15 if (responseStream != null) 16 { 17 using (StreamReader reader = new StreamReader(responseStream, Encoding.Default)) 18 { 19 result = reader.ReadToEnd(); 20 reader.Close(); 21 } 22 } 23 24 Console.WriteLine($"result={result}"); 25 Console.ReadKey();
WebApi 获取请求参数:
参见上面方法2.
3.multipart/form-data
它会将表单的数据处理为一条消息,以标签为单元,用分隔符(这就是boundary的作用)分
开。 由于这种方式将数据有很多部分,它既可以上传键值对,也可以上传文件,甚至多个文
件。当上传的字段是文件时,会有Content-Type来说明文件类型;Content-disposition,用来
说明字段的一些信息。每部分都是以 – – –boundary 开始,紧接着是内容描述信息,然后是回
车,最后是字段具体内容(字段、文本或二进制等)。如果传输的是文件,还要包含文件名和
文件类型信息。消息主体最后以 – – –boundary– – – 标示结束。
如果只是传简单的字段没必要用此种类型。
1 string result = String.Empty; 2 3 string data = $"param1={300}¶m2={600}"; 4 byte[] bytes = Encoding.Default.GetBytes(data); 5 string url = "http://localhost:10486/API/TEST/PostMultipartFormData1"; 6 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 7 request.Method = "POST"; 8 request.ContentType = "multipart/form-data"; 9 request.ContentLength = bytes.Length; 10 Stream requestStream = request.GetRequestStream(); 11 requestStream.Write(bytes,0, bytes.Length); 12 13 HttpWebResponse response = (HttpWebResponse)request.GetResponse(); 14 Stream responseStream = response.GetResponseStream(); 15 if (responseStream != null) 16 { 17 using (StreamReader reader = new StreamReader(responseStream, Encoding.Default)) 18 { 19 result = reader.ReadToEnd(); 20 reader.Close(); 21 } 22 } 23 24 Console.WriteLine($"{result}"); 25 Console.ReadKey();
1 [HttpPost] 2 public string PostMultipartFormData1() 3 { 4 string result = ""; 5 HttpContextBase context = (HttpContextBase)Request.Properties["MS_HttpContext"]; 6 HttpRequestBase request = context.Request; 7 8 Stream stream = request.InputStream; 9 using (StreamReader reader = new StreamReader(stream, Encoding.Default)) 10 { 11 result = reader.ReadToEnd(); 12 } 13 14 return result; 15 }
上传及保存文件1:(参考 https://blog.csdn.net/elie_yang/article/details/80710059 从HTTP的multipart/form-data分析看C#后台 HttpWebRequest文件上传
):
1 string result = ""; 2 string filePath = @"C:UsersPublicPicturesSample Pictures1.jpg"; 3 if (!File.Exists(filePath)) 4 { 5 return; 6 } 7 byte[] bytes = File.ReadAllBytes(filePath); 8 string url = "http://localhost:10486/API/TEST/PostMultipartFormData2"; 9 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 10 // 边界符 11 var boundary = "---------------" + DateTime.Now.Ticks.ToString("x"); 12 request.Method = "POST"; 13 request.Timeout = 60000; 14 request.ContentType = "multipart/form-data; boundary=" + boundary; 15 // 开始边界符 16 var beginBoundary = Encoding.ASCII.GetBytes("--" + boundary + " "); 17 // 结束结束符 18 var endBoundary = Encoding.ASCII.GetBytes("--" + boundary + "-- "); 19 // 换行 20 var newLineBytes = Encoding.UTF8.GetBytes(" "); 21 using (var stream = new MemoryStream()) 22 { 23 // 1.写入开始边界符 24 stream.Write(beginBoundary, 0, beginBoundary.Length); 25 // 2.写入文件(name是参数名,filename是文件完整路径名) 26 var fileHeader = "Content-Disposition: form-data; name={0}; filename={1} " + 27 "Content-Type: application/octet-stream "; 28 var fileHeaderBytes = Encoding.UTF8.GetBytes(string.Format(fileHeader, "file1", filePath)); 29 stream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length); 30 stream.Write(bytes, 0, bytes.Length); 31 // 3.写入新行 32 stream.Write(newLineBytes, 0, newLineBytes.Length); 33 // 4.写入普通的文本值 34 var keyValue = "Content-Disposition: form-data; name={0} {1} "; 35 var keyValueBytes = Encoding.UTF8.GetBytes(string.Format(keyValue, "param1", "ATest")); 36 stream.Write(beginBoundary, 0, beginBoundary.Length); 37 stream.Write(keyValueBytes, 0, keyValueBytes.Length); 38 39 // 5.写入结束边界符 40 stream.Write(endBoundary, 0, endBoundary.Length); 41 request.ContentLength = stream.Length; 42 stream.Position = 0; 43 var tempBuffer = new byte[stream.Length]; 44 stream.Read(tempBuffer, 0, tempBuffer.Length); 45 //写入请求流 46 using (Stream requestStream = request.GetRequestStream()) 47 { 48 requestStream.Write(tempBuffer, 0, tempBuffer.Length); 49 //获取响应 50 using (var response = request.GetResponse()) 51 { 52 using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) 53 { 54 result = reader.ReadToEnd(); 55 } 56 } 57 } 58 59 } 60 61 Console.WriteLine($"{result}"); 62 Console.ReadKey();
1 [HttpPost] 2 public string PostMultipartFormData2() 3 { 4 HttpContextBase context = (HttpContextBase)Request.Properties["MS_HttpContext"]; 5 HttpRequestBase request = context.Request; 6 7 string param1 = request.Form["param1"]; 8 HttpPostedFileBase file = request.Files["file1"]; 9 int length = file.ContentLength; 10 string fileName = file.FileName; 11 string contentType = file.ContentType; 12 file.SaveAs(@"C:UsersPublicPicturesSample Pictures2.jpg"); 13 14 return $"length={length},fileName={fileName},contentType={contentType},param1={param1}"; 15 }
上传及保存文件2:
1 string result = ""; 2 string filePath = @"C:UsersPublicPicturesSample Pictures1.jpg"; 3 if (!File.Exists(filePath)) 4 { 5 return; 6 } 7 byte[] bytes = File.ReadAllBytes(filePath); 8 string url = "http://localhost:10486/API/TEST/PostMultipartFormData3"; 9 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); 10 request.Method = "POST"; 11 request.Timeout = 60000; 12 request.ContentType = "multipart/form-data"; 13 request.ContentLength = bytes.Length; 14 Stream requestStream = request.GetRequestStream(); 15 requestStream.Write(bytes, 0, bytes.Length); 16 using (var response = request.GetResponse()) 17 { 18 using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8)) 19 { 20 result = reader.ReadToEnd(); 21 } 22 } 23 Console.WriteLine($"{result}");
1 [HttpPost] 2 public string PostMultipartFormData3() 3 { 4 HttpContextBase context = (HttpContextBase)Request.Properties["MS_HttpContext"]; 5 HttpRequestBase request = context.Request; 6 7 Stream stream = request.InputStream; 8 byte[] bytes = new byte[stream.Length]; 9 stream.Read(bytes, 0, bytes.Length); 10 stream.Seek(0, SeekOrigin.Begin); 11 FileStream fileStream = File.Create(@"C:UsersPublicPicturesSample Pictures3.jpg"); 12 using (BinaryWriter writer = new BinaryWriter(fileStream, Encoding.Default)) 13 { 14 writer.Write(bytes); 15 writer.Close(); 16 } 17 18 return $"success"; 19 }
参考: https://blog.csdn.net/woaixiaoyu520/article/details/76690686 POST的Content-Type引发的HTTP相关知识思考