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))
{
.....
}
}
}
}
所以,我有一个 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))
{
.....
}
}
}
}