C# 模型绑定无法与asp.net核心webapi控制器操作方法中的流类型参数一起工作。(即使使用自定义streaminputformatter)

C# 模型绑定无法与asp.net核心webapi控制器操作方法中的流类型参数一起工作。(即使使用自定义streaminputformatter),c#,asp.net-web-api,.net-core,C#,Asp.net Web Api,.net Core,我想上传文件到asp net核心web api控制器的操作方法。我正在以“应用程序/八位字节流”的形式发送内容类型。我已经创建了名为StreamInputFormatter的自定义输入格式化程序。正在调用streaminputformatter,但未调用控制器中的操作方法?我也犯了同样的错误 “InvalidOperationException:此流不支持超时。” StreamInputFormatter: public class StreamInputFormatter : IInputFo

我想上传文件到asp net核心web api控制器的操作方法。我正在以“应用程序/八位字节流”的形式发送内容类型。我已经创建了名为StreamInputFormatter的自定义输入格式化程序。正在调用streaminputformatter,但未调用控制器中的操作方法?我也犯了同样的错误

“InvalidOperationException:此流不支持超时。”

StreamInputFormatter:

public class StreamInputFormatter : IInputFormatter
    {
        public bool CanRead(InputFormatterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var contentType = context.HttpContext.Request.ContentType;
            if (contentType == "application/octet-stream")
            {
                return true;
            }
            return false;
        }

        public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }


            var memoryStream = new MemoryStream();
            context.HttpContext.Request.Body.CopyTo(memoryStream);

            return InputFormatterResult.SuccessAsync(memoryStream);
        }
    }
公共类StreamInputFormatter:IIInputFormatter
{
公共bool可读取(InputFormatterContext)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
var contentType=context.HttpContext.Request.contentType;
if(contentType==“应用程序/八位字节流”)
{
返回true;
}
返回false;
}
公共任务ReadAsync(InputFormatterContext上下文)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
var memoryStream=新的memoryStream();
context.HttpContext.Request.Body.CopyTo(memoryStream);
返回InputFormatterResult.SuccessAsync(memoryStream);
}
}
控制器动作方法:

        [HttpPost("{documentType}")]
        public async Task<IActionResult> CreateJob(string documentType, [FromBody]Stream template)
        {

        }
[HttpPost(“{documentType}”)]
公共异步任务CreateJob(字符串documentType,[FromBody]流模板)
{
}

听起来您出现此错误是因为
DefaultObjectValidator
对不受支持的
属性进行了迭代(有关一些信息,请参阅此)

要跳过流模型验证,可以添加

        services.AddMvc(options =>
        {
            ...

            options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
        });

请参阅您的配置。

对于查找此完整示例的任何人,以下内容可能会有所帮助:

Startup.cs

services.AddMvc(options =>
{
    options.InputFormatters.Add(new StreamInputFormatter());
    options.ModelMetadataDetailsProviders.Add(new SuppressChildValidationMetadataProvider(typeof(Stream)));
});
StreamInputFormatter.cs

public class StreamInputFormatter : IInputFormatter
{
    // enter your list here...
    private readonly List<string> _allowedMimeTypes = new List<string>
        { "application/pdf", "image/jpg", "image/jpeg", "image/png", "image/tiff", "image/tif", "application/octet-stream" };


    public bool CanRead(InputFormatterContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }
        var contentType = context.HttpContext.Request.ContentType;
        if (_allowedMimeTypes.Any(x => x.Contains(contentType)))
        {
            return true;
        }

        return false;
    }

    public Task<InputFormatterResult> ReadAsync(InputFormatterContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        // enable stream rewind or you won't be able to read the file in the controller   
        var req = context.HttpContext.Request;
        req.EnableRewind();

        var memoryStream = new MemoryStream();
        context.HttpContext.Request.Body.CopyTo(memoryStream);
        req.Body.Seek(0, SeekOrigin.Begin);
        return InputFormatterResult.SuccessAsync(memoryStream);
    }
}
公共类StreamInputFormatter:IIInputFormatter
{
//在这里输入您的列表。。。
私有只读列表_allowedMimeTypes=新列表
{“application/pdf”、“image/jpg”、“image/jpeg”、“image/png”、“image/tiff”、“image/tif”、“application/octet-stream”};
公共bool可读取(InputFormatterContext)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
var contentType=context.HttpContext.Request.contentType;
if(_allowedMimeTypes.Any(x=>x.Contains(contentType)))
{
返回true;
}
返回false;
}
公共任务ReadAsync(InputFormatterContext上下文)
{
if(上下文==null)
{
抛出新ArgumentNullException(nameof(context));
}
//启用流回放,否则您将无法读取控制器中的文件
var req=context.HttpContext.Request;
req.EnableRewind();
var memoryStream=新的memoryStream();
context.HttpContext.Request.Body.CopyTo(memoryStream);
请求Body.Seek(0,SeekOrigin.Begin);
返回InputFormatterResult.SuccessAsync(memoryStream);
}
}
然后控制器:

public class FileController : BaseController
{
    [HttpPost("customer/{customerId}/file", Name = "UploadFile")]
    [SwaggerResponse(StatusCodes.Status201Created, typeof(UploadFileResponse))]
    [Consumes("application/octet-stream", new string[] { "application/pdf", "image/jpg", "image/jpeg", "image/png", "image/tiff", "image/tif"})]
    public async Task<IActionResult> UploadFile([FromBody] Stream file, [FromRoute] string customerId, [FromQuery] FileQueryParameters queryParameters)
    {
        // file processing here
    }
}
公共类FileController:BaseController
{
[HttpPost(“customer/{customerId}/file”,Name=“UploadFile”)]
[SwaggerResponse(StatusCodes.Status201Created,typeof(UploadFileResponse))]
[使用(“应用程序/八位字节流”,新字符串[]{“应用程序/pdf”,“图像/jpg”,“图像/jpeg”,“图像/png”,“图像/tiff”,“图像/tif”})]
公共异步任务上载文件([FromBody]流文件,[FromRoute]字符串customerId,[FromQuery]文件queryParameters queryParameters)
{
//这里的文件处理
}
}

您在哪里使用了StreamInputFormatter?对于Startup.cs中的中间件?你能分享代码吗?你试过字节数组吗?[FromBody]byte[]Template每当您的复杂类型验证无法帮助您使用SuppressChildValidationMetadataProvider时,最好跳过它
返回InputFormatterResult.SuccessAsync(context.HttpContext.Request.Body)在不复制流的情况下对我有效。