如何使用分段上传将文件(图像)列表和 json 数据上传到 ASP.NET Core Web API Controller ?
我可以成功接收到文件列表,使用 multipart/form-data
内容类型上传:
public async Task<IActionResult> Upload(IList<IFormFile> files)
当然,我可以使用默认的 JSON 格式化程序成功接收格式化为我的对象的 HTTP 请求正文:
public void Post([FromBody]SomeObject value)
但是我怎样才能将这两者结合到一个 Controller Action 中呢?如何上传图像和 JSON 数据并将它们绑定(bind)到我的对象?
最佳答案
简单,代码少,无包装模型
有一个更简单的解决方案,深受 Andrius' answer 的启发.通过使用
ModelBinderAttribute
您不必指定模型或 Binder 提供程序。这样可以节省很多代码。您的 Controller 操作将如下所示:
public IActionResult Upload(
[ModelBinder(BinderType = typeof(JsonModelBinder))] SomeObject value,
IList<IFormFile> files)
{
// Use serialized json object 'value'
// Use uploaded 'files'
}
实现
JsonModelBinder
背后的代码(参见 GitHub 或使用 NuGet package ):
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
public class JsonModelBinder : IModelBinder {
public Task BindModelAsync(ModelBindingContext bindingContext) {
if (bindingContext == null) {
throw new ArgumentNullException(nameof(bindingContext));
}
// Check the value sent in
var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
if (valueProviderResult != ValueProviderResult.None) {
bindingContext.ModelState.SetModelValue(bindingContext.ModelName, valueProviderResult);
// Attempt to convert the input value
var valueAsString = valueProviderResult.FirstValue;
var result = Newtonsoft.Json.JsonConvert.DeserializeObject(valueAsString, bindingContext.ModelType);
if (result != null) {
bindingContext.Result = ModelBindingResult.Success(result);
return Task.CompletedTask;
}
}
return Task.CompletedTask;
}
}
请求示例
这是上面的 Controller 操作 Upload
接受的原始 http 请求的示例。
multipart/form-data
请求被分成多个部分,每个部分由指定的 boundary=12345
分隔。每个部分都在其 Content-Disposition
-header 中分配了一个名称。使用这些名称,默认 ASP.Net-Core
知道哪个部分绑定(bind)到 Controller 操作中的哪个参数。
绑定(bind)到 IFormFile
的文件还需要在请求的第二部分指定一个 filename
。 Content-Type
不是必需的。
另一件需要注意的事情是,json 部分需要反序列化为 Controller 操作中定义的参数类型。所以在这种情况下,SomeObject
类型应该有一个 string
类型的属性 key
。
POST http://localhost:5000/home/upload HTTP/1.1
Host: localhost:5000
Content-Type: multipart/form-data; boundary=12345
Content-Length: 218
--12345
Content-Disposition: form-data; name="value"
{"key": "value"}
--12345
Content-Disposition: form-data; name="files"; filename="file.txt"
Content-Type: text/plain
This is a simple text file
--12345--
使用 Postman 进行测试
Postman可用于调用操作并测试您的服务器端代码。这非常简单,主要是 UI 驱动。创建一个新请求并在 Body-Tab 中选择 form-data。现在您可以为请求的每个部分选择文本和文件。
关于c# - 在 ASP.NET Core Web API 中上传文件和 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41367602/