如何向ASP.NET Core Web API发送multipart/form-data?

21

我正在尝试将图像和文本字段发送到API端点,但是我收到了不支持的内容类型'multipart/form-data;boundary=---------------------------81801171514357'。这是一个ASP.NET Core 2.1 Web API,我有以下内容:

[HttpPost("/api/account"), Authorize]
public void SaveUser(UserModel info)

我的模型:

    [JsonProperty(PropertyName = "avatar")]
    [DataType(DataType.Upload)]
    public IFormFile Avatar { get; set; }

    [JsonProperty(PropertyName = "name")]
    [DataType(DataType.Text)]
    public string Name { get; set; }

然后我使用axios

    var formData = new FormData();
    formData.append("avatar", imageFile);
    formData.append("name", name);
    axios.post("/api/account", formData);

我原本期望这个方法可以被执行,而不是抛出异常。但是怎么做呢?我已经尝试添加:

[Consumes("application/json", "multipart/form-data")]
但是没有成功。 接着我尝试了:
[HttpPost("/api/account"), Authorize]
public void SaveUser([FromForm]UserModel info)

该方法运行,但是info对象上的属性为空 :(

更新: 解决方案是不要使用JsonProperty PropertyName。直接使用变量名即可。


1
当上传带有详细信息的文件时,您应该使用 public void SaveUser(IFormCollection collection)。请参考此链接:https://stackoverflow.com/questions/53825794/webapi-is-it-possible-to-post-an-iformcollection-and-object-in-an-action - Khai Nguyen
有没有演示可以重现你的问题?我使用你当前的代码进行了测试,它正常工作。 - Edward
我有另一种方法: [HttpPost("/api/avatar"), Authorize] public void SaveAvatar(IFormFile avatar)这没有问题。但是当我在模型中添加IFormFile和属性时,就会出现“不支持的内容类型'multipart/form-data'”错误。 - mrcode
现在,我发现我不能使用JsonProperty名称,我必须使用Avatar和Name(属性名称)。然后它就可以正常工作了。能否设置属性的名称? - mrcode
这是解决方案。[https://stackoverflow.com/questions/60275185/file-upload-in-api-in-dotnet-core-wpf-windows-app][1] - Rezaul Khan
3个回答

26

也许你应该尝试使用 [FromForm] 属性为控制器输入和模型装饰一下?web api参数绑定 了解更多信息。

在给定的示例中,您的控制器操作应如下所示:

[HttpPost("/api/account"), Authorize]
public void SaveUser([FromForm]UserModel info)

在模型中:

[FromForm(Name="avatar")]
public IFormFile Avatar { get; set; }

[FromForm(Name="name")]
public string Name { get; set; }

是的,我尝试添加 [FromForm],但是我的模型中的所有属性都为空。 - mrcode
1
尝试在模型属性上添加此属性。 - joostas
1
我发现我不能使用JsonProperty名称,必须使用Avatar和Name(属性名称)。然后它就可以正常工作了。是否可以设置属性的名称? - mrcode
2
在控制器操作和模型定义中,您应该使用[FromForm]属性。至少对我来说是这样的。 - joostas
2
这真的救了我一天!我为这个问题彻夜未眠。非常感谢@joostas。 - Dean Friedland
@joostas:我的模型中有一个包含其他类型的列表,除了列表类型之外,它对所有内容都有效。我正在使用JSON.Stringify从UI发送它。有任何想法为什么它不起作用? - Ranger

2

1-发送多部分文件

            [HttpPost, Route("postimagenews")]
            public IActionResult PostImageNews([FromForm] IFormFile file)
            {
                try
                {
                    if (file == null || file.Length == 0)
                    {
                        return BadRequest("Please send a photo");
                    }
                    //create unique name for file
                    var fileName = Guid.NewGuid().ToString() + Path.GetExtension(file.FileName);
    
                    //set file url
                    var savePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/images/news", fileName);
    
                    using (var stream = new FileStream(savePath, FileMode.Create))
                    {
                        file.CopyTo(stream);
                    }
    
                    return Ok(fileName);
                }
                catch
                {
                    return BadRequest("error in upload image");
                }
            }

2-接收多部分文件

            public static async Task<string> PostImage(string apiendpoint, IFormFile data)
            {
                using (var httpClient = new HttpClient())
                {
                    var multipartContent = new MultipartFormDataContent();
                    var fileContent = new ByteArrayContent(GetFileArray(data));
                    fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
                    multipartContent.Add(fileContent, "file",data.FileName);
                    var resultUploadImage= await httpClient.PostAsync(apiendpoint, multipartContent);
                    if (resultUploadImage.IsSuccessStatusCode)
                    {
                        var fileName=(await resultUploadImage.Content.ReadAsStringAsync()).Replace("\"", "");
                        return fileName;
                    }
                    return "";
                }
            }
    
            public static byte[] GetFileArray(IFormFile file)
            {
                using (var ms = new MemoryStream())
                {
                    file.CopyTo(ms);
                    return ms.ToArray();
                }
            }

使用Postman多部分方式发送文件

enter image description here


-3

这里有一个符合您需求的工作示例

控制器:

[HttpPost]
public async Task<IActionResult> SaveFile([FromForm] IFormFile file) {
  // Your code here
}

而在你的模型内部:

public IFormFile File { get; set; }

如果你不需要它,可以更改async Task<IActionResult>...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接