【问题标题】:HttpClient setting boundary with content-typeHttpClient 设置边界与内容类型
【发布时间】:2013-09-01 05:50:12
【问题描述】:

我正在使用 javascript 与第三方服务进行通信。作为身份验证过程的一部分,他们需要发布消息的“multipart/form”正文,包括要在 md5 中加密的图像,将其添加到包含日期和其他一些内容的字符串中,然后运行 ​​HMAc/SHA1在上面。所以最后他们有多部分正文、日期和身份验证哈希,以便进行身份验证,然后读取图像。

这适用于除 windowsPhone 之外的所有移动设备 ..(我知道,IE 有问题......谁会想到?)。他们的 httpwebrequest 不包含“日期”标头..所以没有身份验证。这意味着我必须为 windows phone 原生并在 C# 中使用新发布的 httpclient 代码。现在我是一个 C# 菜鸟,所以这可能是最简单的解决方案。我已经通过将几乎所有内容传递给 c# 并仅使用 c# 进行发布来获得身份验证,但他们无法读取正文,因为我发现发送边界的唯一方法是将内容定义为 multipartformDatacontent 并发送内容方式更改正文,因此身份验证失败。

我的 javascript 是这样的:

var boundary = "------------ThIs_Is_tHe_bouNdaRY_";
var part1Array = [];
var part1 = "--"+boundary + "\r\n"+
    "Content-Disposition: form-data; name=\"image\"\r\n"+
    "Content-Type: image/jpg\r\n"+
    "\r\n";
var part3Array = [];
var part3 = "\r\n" + boundary +"--";
for(var p1=0; p1<part1.length; p1++){
    part1Array.push(part1.charCodeAt(p1));
}
for(var p3=0; p3<part3.length; p3++){
    part3Array.push(part3.charCodeAt(p3));
}
var bodyContent = part1Array.concat(imageArray,part3Array);

//hash this

var authMessage = bodyContentHash +"\n"+ contentType +"\n"+ todayString +"\n"+ pathandstuff;
// -hmac -sha1 -base64

而c#是:

HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, path);

request.Headers.Date = DateTime.ParseExact(todaydate, "ddd',' dd MMM yyyy HH:mm:ss 'GMT'", new CultureInfo("en-US"), DateTimeStyles.AssumeUniversal);
request.Headers.Add("Accept", "application/json; charset=utf-8");
request.Headers.Add("Authorization", auth);

byte[] body = Convert.FromBase64String(bodyData);
request.Content = new ByteArrayContent(body);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
request.Content.Headers.Add("boundary", "------------ThIs_Is_tHe_bouNdaRY_");

HttpResponseMessage response = client.SendAsync(request).Result;
string resultCode = response.StatusCode.ToString();
string responseBodyAsText = await response.Content.ReadAsStringAsync();

这非常有效.. 正文内容和标题一样正确.. 除了内容类型标题应该是:

request.Content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data, boundary=------------ThIs_Is_tHe_bouNdaRY_");

除非这会引发 System.FormatException 错误。

【问题讨论】:

    标签: c# javascript httpclient content-type boundary


    【解决方案1】:

    使用 HttpClient

     request.Content.Headers.Add("ContentType", "multipart/form-data, boundary=------------ThIs_Is_tHe_bouNdaRY_");
    

    你可以使用 HttpWebRequest

     myHttpWebRequest.Date = DateTime.Now;
     myHttpWebRequest.ContentType = "multipart/form-data, boundary=------------ThIs_Is_tHe_bouNdaRY_";
    

    【讨论】:

    • 谢谢,我实际上刚刚找到了同样的内容 content.headers.add 并让它工作。不幸的是,我无法使用 httpwebrequest 解决方案,因为从我所读到的内容来看,这部分没有填充 wp8 的 Date 标头。谢谢。
    • 我不熟悉 wp8 dev。 httpwebrequest 可以添加自定义 header myHttpWebRequest.Headers.Add("name", "value");
    • 是的,据我所知,这是特定于 WP8 而不是 c#,WindowsPhone8 版本的 HttpWebRequest 中没有“日期”属性。所有其他标头似乎都可以正常工作,但您的请求中从未包含“日期”标头,这就是我不得不使用 HttpClient 的原因。
    • -- httpClient request.Content.Headers 解决方案完美运行 :) 再次感谢。
    【解决方案2】:

    我们通过手动清除并重新添加内容类型而不进行验证来解决此问题 似乎 MediaTypeHeaderValue() 类不喜欢边界标签。

    而不是使用:

    content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data; boundary=----FLICKR_MIME_20140415120129--");
    

    我们做了以下事情:

    content.Headers.Remove("Content-Type");
    content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=----FLICKR_MIME_20140415120129--");
    

    一旦我们进行了这项更改,一切都会正常运行。

    (请注意,这是在 WinRT 上,如果有什么不同的话)

    【讨论】:

      【解决方案3】:

      我在这里发布我的代码,也许这会帮助其他像我一样苦苦挣扎的人,在我的情况下,这可行并将文件上传到我的帐户(不是银行,而是安全的云文件产品)

       public  string UploadFile(string endpointUrl, string filePath, string accessToken)
          {
      
              FileStream fs = null;
              Stream rs = null;
              string result = "";
              try
              {
      
                  string uploadFileName = System.IO.Path.GetFileName(filePath);
      
                  fs = new FileStream(filePath, FileMode.Open, FileAccess.Read);
      
                  var request = (HttpWebRequest)WebRequest.Create(endpointUrl);
                  request.Method = WebRequestMethods.Http.Post;
                  request.AllowWriteStreamBuffering = false;
                  request.SendChunked = true;
                  String CRLF = "\r\n"; // Line separator required by multipart/form-data.        
                  long timestamp = DateTimeOffset.Now.ToUnixTimeSeconds();
      
                  string boundary = timestamp.ToString("x");
                  request.ContentType = "multipart/form-data; boundary=" + boundary;
      
                  request.Headers.Add("Authorization", "Bearer " + accessToken);                             
      
                  long bytesAvailable = fs.Length;
                  long maxBufferSize = 1 * 1024 * 1024;
      
      
                  rs = request.GetRequestStream();
                  byte[] buffer = new byte[50];
                  int read = 0;
      
                  byte[] buf = Encoding.UTF8.GetBytes("--" + boundary + CRLF);
                  rs.Write(buf, 0, buf.Length);
      
                  buf = Encoding.UTF8.GetBytes("Content-Disposition: form-data; name=\"body\"; filename=\"" + uploadFileName + "\"" + CRLF);                
                  rs.Write(buf, 0,buf.Length);
      
                  buf = Encoding.UTF8.GetBytes("Content-Type: application/octet-stream;" + CRLF);
                  rs.Write(buf, 0, buf.Length);
      
                  buf = Encoding.UTF8.GetBytes(CRLF);
                  //writer.append("Content-Type: application/octet-stream;").append(CRLF);
                  rs.Write(buf, 0, buf.Length);
                  rs.Flush();
      
      
                  long bufferSize = Math.Min(bytesAvailable, maxBufferSize);
                  buffer = new byte[bufferSize];
                  while ((read = fs.Read(buffer, 0, buffer.Length)) != 0)
                  {
                      rs.Write(buffer, 0, read);
                  }
                  buf = Encoding.UTF8.GetBytes(CRLF);                
                  rs.Write(buf, 0, buf.Length);
                  rs.Flush();
      
      
                  // End of multipart/form-data.
                  buffer = Encoding.UTF8.GetBytes("--" + boundary + "--" + CRLF);
                  rs.Write(buffer, 0, buffer.Length);
      
                  using (var response = request.GetResponse())
                  using (var responseStream = response.GetResponseStream())
                  using (var reader = new StreamReader(responseStream))
                  {
      
                      result = reader.ReadToEnd();
                  }
              }
              catch (Exception e)
              {
                  result = e.InnerException != null ? e.InnerException.Message : e.Message;  
              }
      
              return result;
          }
      

      【讨论】:

      • 开箱即用,所以我不得不竖起大拇指(:,添加函数 GetResponseWithTimeout 或编辑它
      猜你喜欢
      • 2018-12-18
      • 1970-01-01
      • 2018-03-18
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 1970-01-01
      • 2013-12-25
      • 2016-04-08
      相关资源
      最近更新 更多