使用 Asp.NET Core 3.1 框架将文件上传到服务器时如何将 IFormFile 用作 属性?

How to use IFormFile as property when uploading file to a server using Asp.NET Core 3.1 framework?

我正在尝试创建一个 Web API 来处理存储文件。

Asp.Net 核心 1.0+ 框架附带 IFormFile interface which allows binding the file to a view-model. The documentation about uploading files in ASP.NET Core 声明如下

IFormFile can be used directly as an action method parameter or as a bound model property.

当我使用 IFormFile 作为操作方法的参数时,它没有任何问题。但就我而言,我想将它用作模型上的 属性,因为除了包含自定义验证规则外,我还想绑定其他值。这是我的视图模型。

public class NewFile
{
    [Required]
    [MinFileSize(125), MaxFileSize(5 * 1024 * 1024)]
    [AllowedExtensions(new[] { ".jpg", ".png", ".gif", ".jpeg", ".tiff" })]
    public IFormFile File { get; set; }

    [Required]
    public int? CustomField1 { get; set; }

    [Required]
    public int? CustomField2 { get; set; }

    [Required]
    public int? CustomField3 { get; set; }
}

这是我的客户端请求代码和接受文件的服务器代码。为了简单起见,这两种方法都放在同一个控制器中。但实际上,"client" 方法将被放置到一个单独的应用程序中来发送文件。

[ApiController, Route("api/[controller]")]
public class FilesController : ControllerBase
{
    [HttpGet("client")]
    public async Task<IActionResult> Client()
    {
        using HttpClient client = new HttpClient();

        // we need to send a request with multipart/form-data
        var multiForm = new MultipartFormDataContent
        {
            // add API method parameters
            { new StringContent("CustomField1"), "1" },
            { new StringContent("CustomField2"), "1234" },
            { new StringContent("CustomField3"), "5" },
        };

        // add file and directly upload it
        using FileStream fs = System.IO.File.OpenRead("C:/1.jpg");
        multiForm.Add(new StreamContent(fs), "file", "1.jpg");

        // send request to API
        var responce = await client.PostAsync("https://localhost:123/api/files/store", multiForm);

        return Content("Done");
    }

    [HttpPost("store")]
    public async Task<IActionResult> Store(NewFile model)
    {
        if (ModelState.IsValid)
        {
            try
            {
                var filename = MakeFileName(model, Path.GetFileName(model.File.FileName));

                Directory.CreateDirectory(Path.GetDirectoryName(filename));

                using var stream = new FileStream(filename, FileMode.Create);
                await model.File.CopyToAsync(stream);

                return PhysicalFile(filename, "application/octet-stream");
            }
            catch (Exception e)
            {
                return Problem(e.Message);
            }
        }

        // Are there a better way to display validation errors when using Web API?
        var errors = string.Join("; ", ModelState.Values.SelectMany(v => v.Errors).Select(v => v.ErrorMessage));

        return Problem(errors);
    }
}

当我发出请求时,我收到以下错误,但请求从未到达 store 方法,因为我在那里放置了一个断点,但它从未到达那里。

StatusCode: 415, ReasonPhrase: 'Unsupported Media Type', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent

我怎样才能正确地将文件发送到服务器并让它绑定到我的视图模型上的 File 属性?

ApiController 默认情况下需要 JSON 除非明确说明

使用 [FromForm] 在请求正文中使用表单数据绑定模型。

public async Task<IActionResult> Store([FromForm]NewFile model) {
    //...
}. 

引用Model Binding in ASP.NET Core

the CustomField1, CustomField2, and CustomField3` are null even though they are being sent along as you see in my original question

客户端未正确发送其他字段。您已切换内容和字段名称

var multiForm = new MultipartFormDataContent {
    // add API method parameters
    { new StringContent("1"), "CustomField1" },
    { new StringContent("1234"), "CustomField2" },
    { new StringContent("5"), "CustomField3" },
};