.NET 6 Core C# - 使用二进制 multipart/form-data 上传返回 json 构建休息网络服务
.NET 6 Core C# -building a rest webservice with binary multipart/form-data upload returning json
我正在尝试构建一个 .NET 6.0 C# rest web 服务,接收一个字符串和三个文件,其中一个是二进制图像。
文件没有保存,只是 checked/evaluated 并且结果以 json 结构返回。
该字符串可以是 url 路径参数。
Web 服务应该 运行 在 windows 和 linux docker 容器中。
它只能从 C# 客户端调用,不能从 Internet 访问。
所以 curl 看起来像这样:
curl -X POST -H "Content-Type: multipart/form-data; boundary=------------------------d74496d66958873e" \
--data-binary "@KeyValue.json" \
--data-binary "@Text.txt" \
--data-binary "@Image.tif" \
http://localhost:5000/check/CheckType01
我尝试了一种从 Visual Studio 2022 项目“ASP.NET Core-Web-Api”开始的方法
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/check/{checkType}", (string checkType, HttpContext ctx) =>
{
ctx.Request.EnableBuffering();
ctx.Request.Body.Position = 0;
var reader = new StreamReader(ctx.Request.Body);
var body = Task.Run(async () => await reader.ReadToEndAsync().ConfigureAwait(false));
Console.WriteLine("Parameter: " + checkType);
Console.WriteLine("MultiPart: " + body.Result);
return new { check = "Ok", confidence = 100 }; ;
});
app.Run();
对于包含“KeyValueContent”、“TextContent”和“ImageContent”的三个文件,此代码部分有效:
Output:
Parameter: CheckType01
MultiPart: KeyValueContent&TextContent&ImageContent
Return:
{"check":"Ok","confidence":100}
但我认为这不是解决这个问题的正确方法。
- 文件由“&”分隔,而不是由 header 的边界分隔,因此无法分隔它们。
- 框架应该以某种方式进行分离。
- 多部分 body 是字符串而不是字节数组。
- Web 服务在 body 读取期间被阻止。
我已经阅读了很多关于如何在 ASP.Net Core 中上传文件、关于 webapi-controllers、模型视图控制器、注释、是否最小化 API 等等,
但我仍然不确定正确的方法是什么,我找不到一个有效的最小示例。
我想知道:
- 我应该使用哪种 Visual Studio 2022 起始项目类型?
- 使用什么框架(最小 api、api 带控制器、[ApiController] 属性...)?
- POST 的必要属性 - 二进制 multipart/form-data?
我检查了你的代码,你想一次 post 多个文件,但是 --data-binary 允许你 post 每个请求一个文件,你可以尝试使用 -F到 post 个服务器文件并访问 HttpContext.Request.Form 中的文件。
你可以用 postman 试一下,马上就会发现问题所在:
除了修复 curl 请求以读取多个文件外,您还可以使用 HttpRequest.Form.Files
返回的 IFormFileCollection
(注入 HttpRequest
作为处理程序参数或使用 ctx.Request
访问它) .
还要注意 Task.Run
在这里不仅没有意义而且有害,只需将 lambda 处理程序标记为 async
:
app.MapPost("/check/{checkType}", async (string checkType, HttpRequest request) =>
{
var formFileCollection = request.Form.Files;
foreach (var formFile in request.Form.Files)
{
using var openReadStream = new StreamReader(formFile.OpenReadStream());
var readToEndAsync = await openReadStream.ReadToEndAsync();
// do something here
}
...
return new { check = "Ok", confidence = 100 };
});
我正在尝试构建一个 .NET 6.0 C# rest web 服务,接收一个字符串和三个文件,其中一个是二进制图像。 文件没有保存,只是 checked/evaluated 并且结果以 json 结构返回。 该字符串可以是 url 路径参数。 Web 服务应该 运行 在 windows 和 linux docker 容器中。 它只能从 C# 客户端调用,不能从 Internet 访问。
所以 curl 看起来像这样:
curl -X POST -H "Content-Type: multipart/form-data; boundary=------------------------d74496d66958873e" \
--data-binary "@KeyValue.json" \
--data-binary "@Text.txt" \
--data-binary "@Image.tif" \
http://localhost:5000/check/CheckType01
我尝试了一种从 Visual Studio 2022 项目“ASP.NET Core-Web-Api”开始的方法
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapPost("/check/{checkType}", (string checkType, HttpContext ctx) =>
{
ctx.Request.EnableBuffering();
ctx.Request.Body.Position = 0;
var reader = new StreamReader(ctx.Request.Body);
var body = Task.Run(async () => await reader.ReadToEndAsync().ConfigureAwait(false));
Console.WriteLine("Parameter: " + checkType);
Console.WriteLine("MultiPart: " + body.Result);
return new { check = "Ok", confidence = 100 }; ;
});
app.Run();
对于包含“KeyValueContent”、“TextContent”和“ImageContent”的三个文件,此代码部分有效:
Output:
Parameter: CheckType01
MultiPart: KeyValueContent&TextContent&ImageContent
Return:
{"check":"Ok","confidence":100}
但我认为这不是解决这个问题的正确方法。
- 文件由“&”分隔,而不是由 header 的边界分隔,因此无法分隔它们。
- 框架应该以某种方式进行分离。
- 多部分 body 是字符串而不是字节数组。
- Web 服务在 body 读取期间被阻止。
我已经阅读了很多关于如何在 ASP.Net Core 中上传文件、关于 webapi-controllers、模型视图控制器、注释、是否最小化 API 等等, 但我仍然不确定正确的方法是什么,我找不到一个有效的最小示例。
我想知道:
- 我应该使用哪种 Visual Studio 2022 起始项目类型?
- 使用什么框架(最小 api、api 带控制器、[ApiController] 属性...)?
- POST 的必要属性 - 二进制 multipart/form-data?
我检查了你的代码,你想一次 post 多个文件,但是 --data-binary 允许你 post 每个请求一个文件,你可以尝试使用 -F到 post 个服务器文件并访问 HttpContext.Request.Form 中的文件。
你可以用 postman 试一下,马上就会发现问题所在:
除了修复 curl 请求以读取多个文件外,您还可以使用 HttpRequest.Form.Files
返回的 IFormFileCollection
(注入 HttpRequest
作为处理程序参数或使用 ctx.Request
访问它) .
还要注意 Task.Run
在这里不仅没有意义而且有害,只需将 lambda 处理程序标记为 async
:
app.MapPost("/check/{checkType}", async (string checkType, HttpRequest request) =>
{
var formFileCollection = request.Form.Files;
foreach (var formFile in request.Form.Files)
{
using var openReadStream = new StreamReader(formFile.OpenReadStream());
var readToEndAsync = await openReadStream.ReadToEndAsync();
// do something here
}
...
return new { check = "Ok", confidence = 100 };
});