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