form標簽屬性enctype之multipart/form-data請求詳解


  1. 當form標簽的enctype設置為multipart/form-data瀏覽器都干了些什么呢?

    通常我們在做向服務器提交數據的功能時都會用到表單提交,默認情況下表單的enctype屬性值為application/x-www-form-urlencoded,在想服務器發送數據前,所有的字符都會進行編碼(空格轉換為“+”號,特殊符號轉換為ASCII HEX值,如“<”會轉換為“%3C”);但是當我們想要做一個的包含上傳的數據提交功能時,就必須要將form標簽的enctype屬性設置為multipart/form-data才可以,那么此時瀏覽器都干了些什么,接下來我們抓取一下提交表單時的請求,如下圖所示:

 

 

在請求頭中我們發現Content-Type后面的值中有boundary的鍵后面跟着一串“不明所以”的字符,在Requset PayLoad中每一個Content-Disposition前面都有同樣的字符,boundary的翻譯成中文就是分界線的意思,現在意思已經很明顯了吧,就是說這段“不明所以”的字符串是用來分割表單中的每個數據項的,以圖中最后一個紅色圈選的字符串代表本次數據表單的結尾,當服務器接受到這樣的格式的請求主體信息后 ,會根據Content-Type中的boundary的值來解析對應的數據。

  2.通過代碼來實現form以multipart/form-data的方式來提交數據

  編寫代碼過程中需要注意一下幾點:

  • 每行字符串結束后都需要以“\r\n”換新行,特別注意一下在文件流寫入到請求主體后也要有“\r\n”換行;
  • boundary的值不能和表單數據沖突;
  • Content-Type后面的boundary值的前綴長度不能和Request PayLoad中的boundary前綴長度一樣

  代碼如下:

 HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://localhost:24219/upload.ashx");
 //邊界標識
 string boundary = "WebKitFormBoundary" + Guid.NewGuid().ToString("N"); 
 //開始邊界
 string beginBoundary = "------" + boundary;
 //結束邊界
 string endBoundary = "------" + boundary + "--";
 request.ContentType = "multipart/form-data; boundary=----" + boundary;
 request.Method = "POST";

 Stream requestStream = request.GetRequestStream();
 //鍵值對
 StringBuilder keyValueParam = new StringBuilder();
 keyValueParam.AppendLine(beginBoundary);
 keyValueParam.AppendLine("Content-Disposition: form-data; name=\"name\"");
 keyValueParam.AppendLine();
 keyValueParam.AppendLine("o_1bfj088gv38436s13777eo1dtn1o.jpg");
 keyValueParam.AppendLine(beginBoundary);
 keyValueParam.AppendLine("Content-Disposition: form-data; name=\"chunks\"");
 keyValueParam.AppendLine();
 keyValueParam.AppendLine("5");
 byte[] keyValueByte = Encoding.UTF8.GetBytes(keyValueParam.ToString());
 requestStream.Write(keyValueByte, 0, keyValueByte.Length);

 //文件
 StringBuilder fileParam = new StringBuilder();
 fileParam.AppendLine(beginBoundary);
 fileParam.AppendLine("Content-Disposition: form-data; name=\"file\"; filename=\"370x323-3.jpg\"");
 fileParam.AppendLine("Content-Type: application/octet-stream");
 fileParam.AppendLine();
 byte[] fileParamBytes = Encoding.UTF8.GetBytes(fileParam.ToString());
 requestStream.Write(fileParamBytes, 0, fileParamBytes.Length);
 byte[] fileByte = File.ReadAllBytes(@"C:\Users\CSQ\Desktop\新建文件夾\370x323-2.jpg");
 requestStream.Write(fileByte, 0, fileByte.Length);

 //結束邊界
 StringBuilder endParam = new StringBuilder();
 endParam.AppendLine();
 endParam.AppendLine(endBoundary);//結束邊界
 byte[] endByte = Encoding.UTF8.GetBytes(endParam.ToString());
 requestStream.Write(endByte, 0, endByte.Length);
 HttpWebResponse response = (HttpWebResponse)request.GetResponse();
 Stream responseStream = response.GetResponseStream();
 StreamReader reader = new StreamReader(responseStream);
 string result = reader.ReadToEnd();

這是用HttpWebRequest來編寫的,換做HttpClient類來編寫的話就更簡單了,哈哈,看代碼:

HttpClient client = new HttpClient();
//multipart/form-data類型的請求內容
MultipartFormDataContent httpContents = new MultipartFormDataContent();
byte[] fileByte = File.ReadAllBytes(@"C:\Users\Alan\Desktop\新建文件夾\370x323-2.jpg");
ByteArrayContent fileContent = new ByteArrayContent(fileByte);
fileContent.Headers.ContentType =new MediaTypeHeaderValue("application/octet-stream");
httpContents.Add(fileContent, "file", "370x323-2.jpg");

ByteArrayContent keyValue1 = new ByteArrayContent(Encoding.UTF8.GetBytes("o_1bfj088gv38436s13777eo1dtn1o.jpg"));
httpContents.Add(keyValue1, "name");
ByteArrayContent keyValue2 = new ByteArrayContent(Encoding.UTF8.GetBytes("5"));
httpContents.Add(keyValue2, "chunks");
var response = client.PostAsync("http://localhost:24219/upload.ashx", httpContents).Result;
response.EnsureSuccessStatusCode();

 

是不是很容易啊,完結!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM