.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}

但我认为这不是解决这个问题的正确方法。

我已经阅读了很多关于如何在 ASP.Net Core 中上传文件、关于 webapi-controllers、模型视图控制器、注释、是否最小化 API 等等, 但我仍然不确定正确的方法是什么,我找不到一个有效的最小示例。

我想知道:

我检查了你的代码,你想一次 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 };
});