如何使用 ASP.NET Core 6 minimal api 上传文件?

问题描述 投票:0回答:4

我想在 ASP.NET Core 6 中创建一个简单的文件上传端点,并认为它会像这里描述的那样简单https://dotnetthoughts.net/handling-file-uploads-in-openapi-with-aspnet-core /.

当我定义了一个端点时:

app.MapPost("/upload", (IFormFile file) =>
{
    //Do something with the file
    return Results.Ok();
}).Accepts<IFormFile>("multipart/form-data").Produces(200);

我打电话给端点时收到 415 回复。我收到的消息是这样的:

预期支持的 JSON 媒体类型但得到“multipart/form-data; ...

当我说端点应该接受

multipart/form-data
.

时,不确定为什么它期望支持的json

关于在这里做什么的任何想法或想法?

asp.net .net asp.net-core .net-6.0 minimal-apis
4个回答
7
投票

目前开箱即用的最小 API 绑定支持相当有限。支持的绑定源:

  • 路线价值
  • 查询字符串
  • 标题
  • 正文(作为 JSON)
  • 依赖注入提供的服务
  • 定制

注意:.NET 6 本身不支持从表单绑定

您可以利用自定义绑定或使用 特殊类型处理

app.MapPost("/upload", (HttpRequest request) =>
{
    //Do something with the file
    var files = request.Form.Files;
    return Results.Ok();
})
.Accepts("multipart/form-data")
.Produces(200);

更新

最小 API 应该能够直接绑定

IFormFile
/
IFormFileCollection

app.MapPost("/upload", async (IFormFile file) =>
{
    // ...
});

app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
    foreach (var file in myFiles)
    {
        // ...
    }
});

7
投票

这里需要注意的是,您可以像下面的示例代码一样上传具有any ContentType 的文件。

在这个例子中我选择了

text/plain
ContentType, 但您可以通过将
.Accepts<IFormFile>("text/plain");
行编辑为您想要的 ContentType 来选择您自己的。

app.MapPost("/upload",
    async (HttpRequest request) =>
    {
        using (var reader = new StreamReader(request.Body, System.Text.Encoding.UTF8))
        {

            // Read the raw file as a `string`.
            string fileContent = await reader.ReadToEndAsync();

            // Do something with `fileContent`...
    
            return "File Was Processed Sucessfully!";
        }
    }).Accepts<IFormFile>("text/plain");

Swagger UI也很好的支持:


1
投票

.NET 7 已解决此问题。添加了对 IFormFile 和 IFormFileCollection 的支持。您应该能够在 MediatR 管道中使用它。

参考:.NET 7 对文件上传绑定的最小 API 支持

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.MapPost("/upload", async (IFormFile file) =>
{
    var tempFile = Path.GetTempFileName();
    app.Logger.LogInformation(tempFile);
    using var stream = File.OpenWrite(tempFile);
    await file.CopyToAsync(stream);
});

app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
    foreach (var file in myFiles)
    {
        var tempFile = Path.GetTempFileName();
        app.Logger.LogInformation(tempFile);
        using var stream = File.OpenWrite(tempFile);
        await file.CopyToAsync(stream);
    }
});

app.Run();

0
投票
app.MapPost("/upload",
    async Task<IResult> (HttpRequest request) =>
    {
        if (!request.HasFormContentType)
            return Results.BadRequest();

        var form = await request.ReadFormAsync();

        if (form.Files.Any() == false)
            return Results.BadRequest("There are no files");

        var file = form.Files.FirstOrDefault();

        if (file is null || file.Length == 0)
            return Results.BadRequest("File cannot be empty");

        using var stream = file.OpenReadStream();

        var reader = new StreamReader(stream);
        var text = await reader.ReadToEndAsync();

        return Results.Ok(text);
    }).Accepts<IFormFile>("multipart/form-data"); 
© www.soinside.com 2019 - 2024. All rights reserved.