zoukankan      html  css  js  c++  java
  • 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的方式来提交数据

      编写代码过程中需要注意一下几点:

    • 每行字符串结束后都需要以“ ”换新行,特别注意一下在文件流写入到请求主体后也要有“ ”换行;
    • 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:UsersCSQDesktop新建文件夹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:UsersAlanDesktop新建文件夹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();

    是不是很容易啊,完结!

  • 相关阅读:
    协方差矩阵
    Adobe Photoshop CS6下载安装
    等差数列
    照片产尺寸
    移动立方体算法
    float与double的范围和精度
    C/C++运算符优先级
    通过 Windows API 获取鼠标位置等状态信息
    VC++ 获取鼠标状态,获取鼠标弹起消息
    python动态给对象或者类添加方法
  • 原文地址:https://www.cnblogs.com/caoshiqing/p/6825608.html
Copyright © 2011-2022 走看看