首页 > 解决方案 > 如何在 ASP.NET Core 中将没有文件名的多部分/表单数据文件绑定到 IFormFile

问题描述

在 ASP.NET Core 3.1 中接受 multipart/form-data 参数的简单控制器操作中:

using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace WebApplication
{
    public class Controller : ControllerBase
    {
        [HttpPost("length")]
        public IActionResult Post([FromForm] Input input)
        {
            if (!ModelState.IsValid)
                return new BadRequestObjectResult(ModelState);
            
            return Ok(input.File.Length);
        }
        
        public class Input
        {
            [Required]
            public IFormFile File { get; set; }
        }
    }
}

当我发送带有没有文件名的文件的多部分/表单数据(在RFC 7578下是可接受的)时,它不会被识别为IFormFile. 例如:

using System;
using System.IO;
using System.Threading.Tasks;
using System.Net.Http;

namespace ConsoleApp4
{
    class Program
    {
        static async Task Main(string[] args)
        {
            await Test(withFilename: true);
            await Test(withFilename: false);
        }

        static async Task Test(bool withFilename)
        {
            HttpClient client = new HttpClient();
            
            var fileContent = new StreamContent(new FileStream("/Users/cucho/Desktop/36KB.pdf", FileMode.Open, FileAccess.Read));
            
            var message = new HttpRequestMessage(
                HttpMethod.Post,
                "http://localhost:5000/length"
            );
            
            var content = new MultipartFormDataContent();

            if (withFilename)
            {
                content.Add(fileContent, "File", "36KB.pdf");
            }
            else
            {
                content.Add(fileContent, "File");
            }
            
            message.Content = content;
            
            var response1 = await client.SendAsync(message);

            var withString = withFilename ? "With" : "Without";
            
            Console.WriteLine($"{withString} filename: {(int)response1.StatusCode}");
        }
    }
}

结果是:

With filename: 200
Without filename: 400

如何将没有文件名的文件绑定到 IFormFile 对象?

编辑:

我在ContentDispositionHeaderValueIdentityExtensions中找到了以下方法:

public static class ContentDispositionHeaderValueIdentityExtensions
{
    /// <summary>
    /// Checks if the content disposition header is a file disposition
    /// </summary>
    /// <param name="header">The header to check</param>
    /// <returns>True if the header is file disposition, false otherwise</returns>
    public static bool IsFileDisposition(this ContentDispositionHeaderValue header)
    {
        if (header == null)
        {
            throw new ArgumentNullException(nameof(header));
        }

        return header.DispositionType.Equals("form-data")
            && (!StringSegment.IsNullOrEmpty(header.FileName) || !StringSegment.IsNullOrEmpty(header.FileNameStar));
    }

以及FormFeature中的类似代码,我认为这是它如何决定部件是否为文件。

标签: c#asp.net-core.net-coreasp.net-core-webapi

解决方案


推荐阅读