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.


     

  • 相关阅读:
    default关键字用法
    【转载】SpringMvc和servlet简单对比介绍
    build模式入门,build模式理解(转载)
    tomcat logs 目录下各日志文件的含义
    @Component, @Repository, @Service,@Controller的区别
    在项目开发时为什么要先写接口,再写实现类?
    java 中static关键字注意事项
    this关键字使用注意事项
    两个对象之前如何建立联系
    html页面监听事件
  • 原文地址:https://www.cnblogs.com/muyun/p/3016048.html
Copyright © 2011-2022 走看看