使用 Asp.NET Core 3.1 框架将文件上传到服务器时如何使用 IFormFile 作为属性?
Posted
技术标签:
【中文标题】使用 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? 【发布时间】:2020-04-19 14:26:17 【问题描述】:我正在尝试创建一个可以处理存储文件的 Web API。
Asp.Net core 1.0+ 框架附带IFormFile 接口,允许将文件绑定到视图模型。 documentation about uploading files in ASP.NET Core 声明如下
IFormFile 可以直接用作操作方法参数或用作 绑定模型属性。
当我使用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;
这是我的客户端请求代码和接受文件的服务器代码。为了简单起见,这两种方法都放在同一个控制器中。但实际上,“客户端”方法将被放置在发送文件的单独应用程序中。
[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:“不支持的媒体类型”,版本:1.1, 内容:System.Net.Http.HttpConnectionResponseContent
如何正确地将文件发送到服务器并绑定到我的视图模型上的File
属性?
【问题讨论】:
使用[FromForm]
绑定模型public async Task<IActionResult> Store([FromForm]NewFile model)
。 ApiController
默认情况下需要 JSON,除非另有明确说明
【参考方案1】:
ApiController
默认情况下需要 JSON,除非另有明确说明
使用[FromForm]
在请求正文中使用表单数据绑定模型。
public async Task<IActionResult> Store([FromForm]NewFile model)
//...
.
参考Model Binding in ASP.NET Core
CustomField1、CustomField2 和 CustomField3` 为 null,即使您在我的原始问题中看到它们是一起发送的
客户端未正确发送其他字段。您已切换内容和字段名称
var multiForm = new MultipartFormDataContent
// add API method parameters
new StringContent("1"), "CustomField1" ,
new StringContent("1234"), "CustomField2" ,
new StringContent("5"), "CustomField3" ,
;
【讨论】:
我根据您的建议添加了[FromForm]
,但仍然无效。我从控制器中删除了[ApiController]
属性,并且请求按预期发送到Store
方法。但是,CustomField1
、CustomField2, and
CustomField3` 为空,即使它们正在发送,正如您在我原来的问题中看到的那样。
@John 客户端未正确发送其他字段。您已切换内容和名称
如何在 postman 或 Fiddler 中测试这种类型的 API?你能建议吗?以上是关于使用 Asp.NET Core 3.1 框架将文件上传到服务器时如何使用 IFormFile 作为属性?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Visual Studio 2019 在 Docker 容器中运行 ASP.NET Core 3.1 项目?
创建基于ASP.NET core 3.1 的RazorPagesMovie项目-应用模型类配合基架生成工具生成Razor页面
Json 对象 Asp.net Core 3.1 的最大长度
如何使用 ASP.NET Core 3.1 将 Android 应用程序集成到 Identity Server 以进行身份验证?