C#HttpClient文件流内容错误的边界标题

时间:2018-04-22 16:42:17

标签: c# html http post http-headers

我试图像浏览器(chrome)那样模拟HTTP帖子文件:

HTML

<form name="fnup" method="post" action="action.shtml" enctype="multipart/form-data">    
         <input name="firmfile" id="firmfile" type="file">
         <input type="submit" id="firmbutton" value="Upgrade" class="othsave">
</form>

C#

     public async Task<string> UploadFile(string actionUrl, string filePath)
            {
                var httpClient = new HttpClient();
                //Should I need to add all those headers??? it will help me? what is necessary?
                httpClient.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
                httpClient.DefaultRequestHeaders.Add("Origin", "http://" + ip);
                httpClient.DefaultRequestHeaders.Add("Upgrade-Insecure-Requests", "1");
                httpClient.DefaultRequestHeaders.Add("Pragma", "no-cache");
                httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36");
                httpClient.DefaultRequestHeaders.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8");
                httpClient.DefaultRequestHeaders.Add("Referer", "http://" + ip + "/");
                httpClient.DefaultRequestHeaders.Add("Accept-Encoding", "gzip, deflate");
                httpClient.DefaultRequestHeaders.Add("Accept-Language", "he,en-US;q=0.9,en;q=0.8");
                httpClient.DefaultRequestHeaders.Add("Cookie", "page=DevSet");
                FileStream paramFileStream = File.OpenRead(filePath);
                HttpContent fileStreamContent = new StreamContent(paramFileStream);
                using (var content = new MultipartFormDataContent())
                {
                    content.Add(fileStreamContent, "firmfile", Path.GetFileName(filePath));
                    HttpResponseMessage response = await httpClient.PostAsync(actionUrl, content);

                    string res = await response.Content.ReadAsStringAsync();
                    return await Task.Run(() => res);
                }
            }

C#示例在我的服务器中无效,我无法理解为什么......

在查看Wireshark之​​后,我发现了一些不同之处:

Chrome

enter image description here

C#

enter image description here

问题:

1)如何从"filename*=utf-8''VP445_all_V116.bin"中删除Content-Disposition 2)为什么我在Chrome中看不到第二行Content-Type: application/octet-stream? 3)内容长度也不相同(即使它是同一个文件)
4)底线是C#不工作且chrome正在工作,服务器端对我来说是黑盒子,所以我需要猜测我在C#post请求中做错了什么。

1 个答案:

答案 0 :(得分:1)

找到解决方案。

问题确实是'Content-Type: application/octet-stream'

为什么HttpClient StreamContent未添加自动?我真的不知道。

将解决方法添加到手动

主要想法是从这里: https://github.com/paulcbetts/ModernHttpClient/issues/92

这是固定的C#代码:

  public async Task<string> UploadFile(string actionUrl, string filePath)
        {
            var httpClient = new HttpClient();
            httpClient.Timeout = TimeSpan.FromMilliseconds(FileReqTimeout);

            FileStream fileStream = File.OpenRead(filePath);
            var streamContent = new StreamContent(fileStream);
            streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            streamContent.Headers.ContentDisposition.Name = "\"firmfile\"";
            streamContent.Headers.ContentDisposition.FileName = "\"" + Path.GetFileName(filePath) + "\"";
            streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
            string boundary = Guid.NewGuid().ToString();
            var content = new MultipartFormDataContent(boundary);
            content.Headers.Remove("Content-Type");
            content.Headers.TryAddWithoutValidation("Content-Type", "multipart/form-data; boundary=" + boundary);
            content.Add(streamContent);
            HttpResponseMessage response = null;
            try
            {
                response = await httpClient.PostAsync(actionUrl, content, cts.Token);
            }
            catch (WebException ex)
            {
                // handle web exception
                return null;
            }
            catch (TaskCanceledException ex)
            {
                if (ex.CancellationToken == cts.Token)
                {
                    // a real cancellation, triggered by the caller
                    return null;
                }
                else
                {
                    // a web request timeout (possibly other things!?)
                    return null;
                }
            }

            try
            {
                response.EnsureSuccessStatusCode();
            }
            catch (Exception)
            {
                return null;
            };

            string res = await response.Content.ReadAsStringAsync();
            return await Task.Run(() => res);
        }
    }