HttpRequest 适用于 postman 但不适用于 .Net Core

HttpRequest works in postman but not in .Net Core

所以,我有一个 POST 上传文件的请求。我可以通过这样的简单设置在邮递员内部完成该请求: Body: form-data, body 只有一项。键=文件,值=xxxx.pdf

无权限。邮递员控制台的最终工作请求如下所示:

Request Headers
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: 8d5df709-8f9e-48e2-bf20-f300b24d4be8
Host: api.xxxx.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Type: multipart/form-data; boundary=--------------------------138420394858496796018969
Cookie: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Content-Length: 976797
Request Body
file: undefined

这有效,文件已上传。但是当我在 .net Core 中做同样的事情时,它每次都会失败(400 - 错误的请求)

using (var message = new HttpRequestMessage(HttpMethod.Post, uploadUri))
{
    using (var fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
    using (var formDataContent = new MultipartFormDataContent())
    {
        using (var fileContent = new StreamContent(fileStream))
        {
            formDataContent.Add(fileContent, "file");
            message.Content = formDataContent;

            using (var response = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead))
            {
                response.EnsureSuccessStatusCode();
            }
        }
    }
}

编辑:我能看到的唯一区别是 content-disposition header 被添加到 StreamContent。但是我无法删除此 header.

编辑:在与 API 的开发人员交谈后,问题是 100% 的 body 和 header 请求。 Api 不想要 content-disposition header 并且期望 body multipart/form-data 与 pair file=byteArray

可能是安全问题,尝试在 HTTP 请求代码之前添加这个

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;

我相信你缺少 Content-Type header 值集:

fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");

我已经用 *.jpg 文件进行了测试,它工作正常:

using (var multipartFormContent = new MultipartFormDataContent())
{
   //Load the file and set the file's Content-Type header
   var fileStreamContent = new StreamContent(File.OpenRead(filePath));
   fileStreamContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");

   //Add the file to form
   multipartFormContent.Add(fileStreamContent, name: "file", fileName: filePath);

   //Send it
   var response = await new HttpClient().PostAsync("http://localhost:5000/[Controller]/[Action]", multipartFormContent);
   response.EnsureSuccessStatusCode();
}

所以最后。评论中的 Oliver 为我指明了正确的方向,而通过 Fiddler,我找到了解决方案。问题出在 content-type header 中。这个header在postman里面生成的时候,boundary是没有引号的。 Httpclient hovewer 会自动添加这些。这就是我的请求被拒绝的原因。

工作代码:

using (var message = new HttpRequestMessage(HttpMethod.Post, uploadUri))
{
    var boundary = $"--------------------------{Guid.NewGuid().ToString("N").ToUpper()}";

    using (var fileStream = new FileStream(fileInfo.FullName, FileMode.Open, FileAccess.Read))
    using (var content = new MultipartFormDataContent(boundary))
    {
        content.Headers.Remove("Content-Type");
        content.Headers.TryAddWithoutValidation("Content-Type", $"multipart/form-data; boundary={boundary}");

        using (var fileContent = new StreamContent(fileStream))
        {
            fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data");
            fileContent.Headers.ContentDisposition.Name = "\"file\"";
            fileContent.Headers.ContentDisposition.FileName = $"\"{fileInfo.Name}\"";
            fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");

            content.Add(fileContent);
            message.Content = content;

            using (var response = await httpClient.SendAsync(message, HttpCompletionOption.ResponseHeadersRead))
            {
                .....
            }
        }
    }
}