【问题标题】:Unexpected behaviour when uploading multiple files using multipart/form-data media type in .NET Core Web API?在 .NET Core Web API 中使用 multipart/form-data 媒体类型上传多个文件时出现意外行为?
【发布时间】:2020-12-02 15:09:34
【问题描述】:

我在我的项目中使用 .NET core 3.1,我需要上传多个文件。下面是我的模型:

public class ProductImageDetailsDto
{
    [Display(Name = "product image")]
    [AllowedExtensions(new string[] { ".jpg", ".png" })]
    public IFormFile ProductImage { get; set; }
}

下面是我的 WebAPI,我接受 List<ProductImageDetailsDto> 作为参数:

    [HttpPut("UpdateProductImagesByProductId/{id}")]
    public async Task<IActionResult> UpdateProdutImagesByProductId(Guid id, [FromForm] List<ProductImageDetailsDto> productImages)
    {
        ApiResponseModel<string> apiResponse = await _productDetailServices.UpdateProductImagesByProductIdAsync(id, productImages, new Guid(UserId));
        return Ok(apiResponse);
    }

当我从 postman 或 swagger 传递数据时,API 端没有收到任何内容,productImages 参数有 count = 0。我像这样从邮递员那里传递数据:

productImages[0].ProductImage :  file
productImages[1].ProductImage :  file1

但如果我修改我的 ProductImageDetailsDto 类并添加更多字段,让我们说 IsDefault 如下所示:

public class ProductImageDetailsDto
{
    [Display(Name = "product image")]
    [AllowedExtensions(new string[] { ".jpg", ".png" })]
    public IFormFile ProductImage { get; set; }
    public bool IsDefault { get; set; }
}

如果我像这样从邮递员那里传递数据:

productImages[0].ProductImage :  file
productImages[0].IsDefault:      false
productImages[1].ProductImage :  file1
productImages[1].IsDefault:      true

一切似乎都运行良好,我正在接收数据,即 API 端的 ProductImage 和 IsDefault。

那么如果我在ProductImageDetailsDto 中只保留IFormFile 字段,会有什么问题。我有什么遗漏或做错了什么吗?提前致谢。

注意:我不想将List&lt;IFormFile&gt;IFormFileCollection 作为API 中的参数类型,因为我想使用自定义验证器[AllowedExtension] 来验证图像,这就是我在模型中创建IFormFile 属性的原因并接受List&lt;ProductImageDetailsDto&gt; 作为参数。

【问题讨论】:

  • 嗨@Sunny,你是如何设计AllowedExtensions属性的?如果我不使用这样的属性,我可以使用你在邮递员中所做的来接收数据。请分享你的AllowedExtensions代码和截图你是如何使用邮递员的(分享你的请求头和表单数据是什么)。
  • 另外,能否分享一下你的Startup.cs,你用的是asp.net core web api吗?你的控制器是什么?控制器是用[ApiController]装饰的吗?请分享控制器更详细。
  • @Rena 我想 AllowedExtensions 没有问题,因为我试图将它注释掉,但它没有用。是的,我使用的是 .NET Core Web API 模板,控制器用 [ApiController] 装饰。
  • 嗨 @Sunny,您介意与我们分享您的 Starup.cs 吗?
  • @Rena 这个问题有点奇怪。如果我在 ProductImageDetailsDto 中再取一个字段,假设 IsDefault 作为 bool 字段,如果我像 productImages[0].IsDefault: false 和 ProductImage 参数一样传递它,那么一切正常。但如果我只传递 productImages[0].ProductImage,那么我在 API 中什么也得不到。

标签: asp.net-core asp.net-core-webapi multipartform-data asp.net-core-3.1


【解决方案1】:

如果您只想传递productImages[0].ProductImage,请更改您的代码,删除[ApiController][FromForm]

// [ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{     
    [HttpPut("UpdateProductImagesByProductId/{id}")]
    public async Task<IActionResult> UpdateProdutImagesByProductId(Guid id, List<ProductImageDetailsDto> productImages)
    {

        return Ok();
    }
}

结果:

更新:

如果您想维护[ApiController] 和自定义验证,请在操作中添加自定义属性并删除[FromForm],如下所示:

public async Task<IActionResult> UpdateProdutImagesByProductId(Guid id,[AllowedExtensions(new string[] { ".jpg", ".png"})] List<IFormFile> files)

结果:

【讨论】:

  • 你能解释一下我为什么要删除 [ApiController] 和 [FromForm]
  • 这似乎是设计使然。我提出了一个 github 问题并等待 PG 的解释。您可以关注:github.com/dotnet/aspnetcore/issues/28273。如果我的解决方法对您有用。请您接受作为答案。
  • 我无法删除 [ApiController] 因为在同一个控制器中还有其他 API。我尝试删除 [ApiController] 但它没有用。所以你能够产生我的问题。对吗?
  • 感谢您在 github 上提出问题。
  • 是的,我可以和你重现同样的问题。I tried removing [ApiController] but it didn't work.。那么你是否也删除了[FromForm]?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 2016-12-14
  • 2016-08-21
  • 2015-10-23
  • 1970-01-01
  • 2021-05-18
相关资源
最近更新 更多