使用 HttpClient 上传多部分表单文件
Uploading multipart form files with HttpClient
我正在尝试使用 Support Bee API 创建附件,如下所述:
https://supportbee.com/api#create_attachment
我编写了一个服务,它使用 HttpClient
使用文件名创建和发送请求。
如果我在 Postman 中测试,它会成功。我正在为 body 使用 form-data
并且只是从 UI:
选择要上传的文件
当我尝试通过我的 HttpClient
服务上传它时它不起作用:
public async Task<string> CreateAttachmentAsync(string fileName)
{
// "client" is HttpClient provided via D.I.
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StreamContent(new FileStream(fileName, FileMode.Open)), "files[]");
using (HttpResponseMessage response = await client.PostAsync(
"https://xxx.supportbee.com/attachments?auth_token=xxx",
content))
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
这会导致 500 内部服务器错误。检查 MultipartFormDataContent
object 我可以看到它的 header 值是自动设置的:
{
Content-Type: multipart/form-data; boundary="c9be3778-4de5-4460-9929-adcaa6bdda79"
Content-Length: 164
}
我也试过先将文件读取到字节数组,然后使用 ByteArrayContent
而不是 StreamContent
无济于事。响应没有提供任何帮助,但由于请求在 Postman 中有效,我的代码肯定有问题,但我不知道还能尝试什么。
编辑:我使用 Fiddler 进行了测试,以将成功的 Postman 请求与我的代码进行比较。这是邮递员的请求:
POST
https://xxx.supportbee.com/attachments?auth_token=xxx
HTTP/1.1 User-Agent: PostmanRuntime/7.22.0 Accept: / Cache-Control:
no-cache Postman-Token: f84d22fa-b4b1-4bf5-b183-916a786c6385 Host:
xx.supportbee.com Content-Type: multipart/form-data;
boundary=--------------------------714700821471353664787346
Accept-Encoding: gzip, deflate, br Content-Length: 241 Connection:
close
----------------------------714700821471353664787346 Content-Disposition: form-data; name="files[]"; filename="sample.txt"
Content-Type: text/plain
This contains example text.
----------------------------714700821471353664787346--
我的代码请求失败:
POST
https://xxx.supportbee.com/attachments?auth_token=xxx
HTTP/1.1 Host: xxx.supportbee.com Accept: / Accept-Encoding:
gzip, deflate, br Connection: close Content-Type: multipart/form-data;
boundary="ea97cbc1-70ea-4cc4-9801-09f5feffc763" Content-Length: 206
--ea97cbc1-70ea-4cc4-9801-09f5feffc763 Content-Disposition: form-data; name="files[]"; filename=sample; filename*=utf-8''sample
This contains example text.
--ea97cbc1-70ea-4cc4-9801-09f5feffc763--
我能看到的不同之处在于,Postman 中的各个部分都有自己的文件 Content-Type: text/plain
header,而我的没有。我无法添加它,因为如果我尝试 content.Headers.Add("Content-Type", "text/plain");
它会失败并显示“无法添加值,因为 header 'Content-Type' 不支持多个值。”
首先,重要的是要注意 500 响应类似于未处理的异常,也就是说,这是他们端的错误,或多或少不可能确定您做错了什么。我建议向他们报告,虽然我不熟悉 Support Bee,但我希望他们有很好的支持人员可以帮助您解决问题。 :)
但是如果你想玩猜谜游戏,我同意你成功的 Postman 调用和你的代码之间的细微差别是一个很好的起点。对于 header,请注意 content
是 MultipartFormDataContent
。你实际上想把它设置在 StreamContent
object.
另外,查看 headers Postman 发送的请求,看看 Content-Disposition
是否包含 filename
。如果 API 需要它,您可能也需要将它添加到您的代码中。
以下是两者的操作方法:
var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
content.Add(fileContent, "files[]", Path.GetFileName(path));
如果这不是问题,请查看 Postman 中请求 body 的 "raw" 版本,以及那 11 个请求 header,看看您是否能发现您可能还缺少其他任何东西。
我正在尝试使用 Support Bee API 创建附件,如下所述: https://supportbee.com/api#create_attachment
我编写了一个服务,它使用 HttpClient
使用文件名创建和发送请求。
如果我在 Postman 中测试,它会成功。我正在为 body 使用 form-data
并且只是从 UI:
当我尝试通过我的 HttpClient
服务上传它时它不起作用:
public async Task<string> CreateAttachmentAsync(string fileName)
{
// "client" is HttpClient provided via D.I.
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new StreamContent(new FileStream(fileName, FileMode.Open)), "files[]");
using (HttpResponseMessage response = await client.PostAsync(
"https://xxx.supportbee.com/attachments?auth_token=xxx",
content))
{
string responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
这会导致 500 内部服务器错误。检查 MultipartFormDataContent
object 我可以看到它的 header 值是自动设置的:
{ Content-Type: multipart/form-data; boundary="c9be3778-4de5-4460-9929-adcaa6bdda79" Content-Length: 164 }
我也试过先将文件读取到字节数组,然后使用 ByteArrayContent
而不是 StreamContent
无济于事。响应没有提供任何帮助,但由于请求在 Postman 中有效,我的代码肯定有问题,但我不知道还能尝试什么。
编辑:我使用 Fiddler 进行了测试,以将成功的 Postman 请求与我的代码进行比较。这是邮递员的请求:
POST https://xxx.supportbee.com/attachments?auth_token=xxx HTTP/1.1 User-Agent: PostmanRuntime/7.22.0 Accept: / Cache-Control: no-cache Postman-Token: f84d22fa-b4b1-4bf5-b183-916a786c6385 Host: xx.supportbee.com Content-Type: multipart/form-data; boundary=--------------------------714700821471353664787346 Accept-Encoding: gzip, deflate, br Content-Length: 241 Connection: close
----------------------------714700821471353664787346 Content-Disposition: form-data; name="files[]"; filename="sample.txt" Content-Type: text/plain
This contains example text. ----------------------------714700821471353664787346--
我的代码请求失败:
POST https://xxx.supportbee.com/attachments?auth_token=xxx HTTP/1.1 Host: xxx.supportbee.com Accept: / Accept-Encoding: gzip, deflate, br Connection: close Content-Type: multipart/form-data; boundary="ea97cbc1-70ea-4cc4-9801-09f5feffc763" Content-Length: 206
--ea97cbc1-70ea-4cc4-9801-09f5feffc763 Content-Disposition: form-data; name="files[]"; filename=sample; filename*=utf-8''sample
This contains example text. --ea97cbc1-70ea-4cc4-9801-09f5feffc763--
我能看到的不同之处在于,Postman 中的各个部分都有自己的文件 Content-Type: text/plain
header,而我的没有。我无法添加它,因为如果我尝试 content.Headers.Add("Content-Type", "text/plain");
它会失败并显示“无法添加值,因为 header 'Content-Type' 不支持多个值。”
首先,重要的是要注意 500 响应类似于未处理的异常,也就是说,这是他们端的错误,或多或少不可能确定您做错了什么。我建议向他们报告,虽然我不熟悉 Support Bee,但我希望他们有很好的支持人员可以帮助您解决问题。 :)
但是如果你想玩猜谜游戏,我同意你成功的 Postman 调用和你的代码之间的细微差别是一个很好的起点。对于 header,请注意 content
是 MultipartFormDataContent
。你实际上想把它设置在 StreamContent
object.
另外,查看 headers Postman 发送的请求,看看 Content-Disposition
是否包含 filename
。如果 API 需要它,您可能也需要将它添加到您的代码中。
以下是两者的操作方法:
var fileContent = new StreamContent(File.OpenRead(path));
fileContent.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
content.Add(fileContent, "files[]", Path.GetFileName(path));
如果这不是问题,请查看 Postman 中请求 body 的 "raw" 版本,以及那 11 个请求 header,看看您是否能发现您可能还缺少其他任何东西。