HttpClient正在设置内容类型为的边界

本文关键字:类型 边界 设置 HttpClient | 更新日期: 2023-09-27 18:29:21

我正在使用javascript与第三方服务进行通信。作为身份验证过程的一部分,他们需要帖子的"多部分/表单"主体,其中包括要在md5中加密的图像,这被添加到一个字符串中,包括日期和其他一些东西,然后在上面运行HMAc/SHA1。因此,最终他们有了多部分主体、日期和身份验证哈希,以便进行身份验证,然后读取图像。

这适用于除windowsPhone之外的所有移动设备。。(我知道,IE有问题……谁会想到呢?)。他们的httpwebrequest不包括"Date"标头。。因此没有身份验证。这意味着我必须使用windows phone的原生版本,并使用C#中最新发布的httpclient代码。现在我是一个C#noob,所以这可能是一个简单的解决方案。我已经通过将几乎所有的东西都传递给C#并使用C#进行发布来实现身份验证,但他们无法读取主体,因为我发现发送边界的唯一方法是将内容定义为multipartformDataContext并以这种方式发送内容,从而更改主体,因此身份验证失败。

我的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错误之外。

HttpClient正在设置内容类型为的边界

我们通过手动清除并重新添加未经验证的内容类型来解决此问题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上)

使用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_";

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

 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;
    }