zoukankan      html  css  js  c++  java
  • HTTP的POST请求的详细构造[实现机器提交表单含上传文件及普通文本域]

          最近用C#做测试网站的服务程序,由于有些接口需要真实的测试数据。比如提交表单中的文本域和文件域,但.Net中只提供了简单的单独提交文本或文件的方法,所以只能自己构造格式为

    multipart/form-data

    的HTTP请求,而让我更加了解了HTTP请求的格式。

          下面是在Google搜索后的一个解决方案,原链接:http://stackoverflow.com/questions/566462/upload-files-with-httpwebrequest-multipart-form-data

     方法1:上传文本域及一个文件[测试成功]

     1         //发送对应表单文本域和一个文件[函数中的输出语句自己调节]
     2         public static void HttpUploadFile(string url, string file, string paramName, string contentType, NameValueCollection nvc)
     3         {
     4             Console.WriteLine(string.Format("Uploading {0} to {1}", file, url));
     5             string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x");
     6             byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
     7 
     8             HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);
     9             wr.ContentType = "multipart/form-data; boundary=" + boundary;
    10             wr.Method = "POST";
    11             wr.KeepAlive = true;
    12             wr.Credentials = System.Net.CredentialCache.DefaultCredentials;
    13 
    14             Stream rs = wr.GetRequestStream();
    15 
    16             string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
    17             foreach (string key in nvc.Keys)
    18             {
    19                 rs.Write(boundarybytes, 0, boundarybytes.Length);
    20                 string formitem = string.Format(formdataTemplate, key, nvc[key]);
    21                 byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
    22                 rs.Write(formitembytes, 0, formitembytes.Length);
    23             }
    24             rs.Write(boundarybytes, 0, boundarybytes.Length);
    25 
    26             string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
    27             string header = string.Format(headerTemplate, paramName, file, contentType);
    28             byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    29             rs.Write(headerbytes, 0, headerbytes.Length);
    30 
    31             FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
    32             byte[] buffer = new byte[4096];
    33             int bytesRead = 0;
    34             while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
    35             {
    36                 rs.Write(buffer, 0, bytesRead);
    37             }
    38             fileStream.Close();
    39 
    40             byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n");
    41             rs.Write(trailer, 0, trailer.Length);
    42             rs.Close();
    43 
    44             WebResponse wresp = null;
    45             try
    46             {
    47                 wresp = wr.GetResponse();
    48                 Stream stream2 = wresp.GetResponseStream();
    49                 StreamReader reader2 = new StreamReader(stream2);
    50                 Console.WriteLine(string.Format("File uploaded, server response is: {0}", reader2.ReadToEnd()));
    51             }
    52             catch (Exception ex)
    53             {
    54                 //log.Error("Error uploading file", ex);
    55                 if (wresp != null)
    56                 {
    57                     wresp.Close();
    58                     wresp = null;
    59                 }
    60             }
    61             finally
    62             {
    63                 wr = null;
    64             }
    65         }
    //使用的例子
    //nvc中存放表单文本域的键值对
    //image/jpeg是上传文件的格式
        NameValueCollection nvc = new NameValueCollection();
        nvc.Add("id", "TTR");
        nvc.Add("btn-submit-photo", "Upload");
        HttpUploadFile("http://your.server.com/upload", 
             @"C:\test\test.jpg", "file", "image/jpeg", nvc);

    方法2:上传表单文本域和多个文件[我没测试成功]

     1 public static  void UploadFilesToRemoteUrl(string url, string[] files, string
     2 logpath, NameValueCollection nvc)
     3 {
     4 
     5     long length = 0;
     6     string boundary = "----------------------------" +
     7     DateTime.Now.Ticks.ToString("x");
     8 
     9 
    10     HttpWebRequest httpWebRequest2 = (HttpWebRequest)WebRequest.Create(url);
    11     httpWebRequest2.ContentType = "multipart/form-data; boundary=" +
    12     boundary;
    13     httpWebRequest2.Method = "POST";
    14     httpWebRequest2.KeepAlive = true;
    15     httpWebRequest2.Credentials =
    16     System.Net.CredentialCache.DefaultCredentials;
    17 
    18 
    19 
    20     Stream memStream = new System.IO.MemoryStream();
    21 
    22     byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" +
    23     boundary + "\r\n");
    24 
    25 
    26     string formdataTemplate = "\r\n--" + boundary +
    27     "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";
    28 
    29     foreach (string key in nvc.Keys)
    30     {
    31         string formitem = string.Format(formdataTemplate, key, nvc[key]);
    32         byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
    33         memStream.Write(formitembytes, 0, formitembytes.Length);
    34     }
    35 
    36 
    37     memStream.Write(boundarybytes, 0, boundarybytes.Length);
    38 
    39     string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";
    40 
    41     for (int i = 0; i < files.Length; i++)
    42     {
    43 
    44         //string header = string.Format(headerTemplate, "file" + i, files[i]);
    45         string header = string.Format(headerTemplate, "uplTheFile", files[i]);
    46 
    47         byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
    48 
    49         memStream.Write(headerbytes, 0, headerbytes.Length);
    50 
    51 
    52         FileStream fileStream = new FileStream(files[i], FileMode.Open,
    53         FileAccess.Read);
    54         byte[] buffer = new byte[1024];
    55 
    56         int bytesRead = 0;
    57 
    58         while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
    59         {
    60             memStream.Write(buffer, 0, bytesRead);
    61 
    62         }
    63 
    64 
    65         memStream.Write(boundarybytes, 0, boundarybytes.Length);
    66 
    67 
    68         fileStream.Close();
    69     }
    70 
    71     httpWebRequest2.ContentLength = memStream.Length;
    72 
    73     Stream requestStream = httpWebRequest2.GetRequestStream();
    74 
    75     memStream.Position = 0;
    76     byte[] tempBuffer = new byte[memStream.Length];
    77     memStream.Read(tempBuffer, 0, tempBuffer.Length);
    78     memStream.Close();
    79     requestStream.Write(tempBuffer, 0, tempBuffer.Length);
    80     requestStream.Close();
    81 
    82 
    83     WebResponse webResponse2 = httpWebRequest2.GetResponse();
    84 
    85     Stream stream2 = webResponse2.GetResponseStream();
    86     StreamReader reader2 = new StreamReader(stream2);
    87 
    88 
    89     MessageBox.Show(reader2.ReadToEnd());
    90 
    91     webResponse2.Close();
    92     httpWebRequest2 = null;
    93     webResponse2 = null;
    94 }

    原理解释:

    详细见链接。下面简单复制过来的。


    I believe that you are not building the request body correctly. First, you need to include part boundary (random text) in content type header. For example,

    Content-Type: multipart/form-data; boundary=----WebKitFormBoundarySkAQdHysJKel8YBM

    Now format of request body will be something like

    ------WebKitFormBoundarySkAQdHysJKel8YBM 
    Content-Disposition: form-data;name="key"
    
    KeyValueGoesHere
    ------WebKitFormBoundarySkAQdHysJKel8YBM 
    Content-Disposition: form-data;name="param2"
    
    ValueHere
    ------WebKitFormBoundarySkAQdHysJKel8YBM 
    Content-Disposition: form-data;name="fileUpload"; filename="y1.jpg"
    Content-Type: image/jpeg 
    
    [image data goes here]

    I will suggest you to use tool such as Fiddler to understand how these requests are built.


     

  • 相关阅读:
    A1052. Linked List Sorting (25)
    A1032. Sharing (25)
    A1022. Digital Library (30)
    A1071. Speech Patterns (25)
    A1054. The Dominant Color (20)
    A1060. Are They Equal (25)
    A1063. Set Similarity (25)
    电子码表
    矩阵键盘
    对象追踪、临时对象追踪、绝对坐标与相对坐标
  • 原文地址:https://www.cnblogs.com/muyun/p/3016048.html
Copyright © 2011-2022 走看看