You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ASP.NET Core控制器如何绑定HTTP请求体中的二进制数据?

问题根源

IFormFile 默认仅支持解析 multipart/form-data 格式的请求体,你直接发送Raw二进制流时,ASP.NET Core 2.1 默认没有对应的模型绑定逻辑,所以参数始终为null。


解决方案:自定义Raw请求体模型绑定

步骤1:实现自定义模型绑定器

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using System;
using System.IO;
using System.Threading.Tasks;

public class RawRequestBodyModelBinder : IModelBinder
{
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
            throw new ArgumentNullException(nameof(bindingContext));

        var request = bindingContext.HttpContext.Request;
        if (request.ContentLength == null || request.ContentLength == 0)
        {
            bindingContext.Result = ModelBindingResult.Failed();
            return;
        }

        // 支持绑定到byte数组、Stream、IFormFile三种类型参数
        if (bindingContext.ModelType == typeof(byte[]))
        {
            using var ms = new MemoryStream();
            await request.Body.CopyToAsync(ms);
            bindingContext.Result = ModelBindingResult.Success(ms.ToArray());
        }
        else if (bindingContext.ModelType == typeof(Stream))
        {
            bindingContext.Result = ModelBindingResult.Success(request.Body);
        }
        else if (bindingContext.ModelType == typeof(IFormFile))
        {
            var formFile = new FormFile(request.Body, 0, request.ContentLength.Value, 
                bindingContext.FieldName, bindingContext.FieldName)
            {
                Headers = request.Headers,
                ContentType = request.ContentType
            };
            bindingContext.Result = ModelBindingResult.Success(formFile);
        }
        else
        {
            bindingContext.Result = ModelBindingResult.Failed();
        }
    }
}

步骤2:注册绑定器(两种方式二选一即可)

方式1:全局注册(推荐,所有对应类型参数都生效)

先实现绑定器提供者:

public class CustomModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context.Metadata.ModelType == typeof(byte[]) 
            || context.Metadata.ModelType == typeof(Stream) 
            || context.Metadata.ModelType == typeof(IFormFile))
        {
            return new RawRequestBodyModelBinder();
        }
        return null;
    }
}

在Startup.cs的ConfigureServices中注册:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc(options =>
    {
        // 插入到绑定器列表首位,优先级最高
        options.ModelBinderProviders.Insert(0, new CustomModelBinderProvider());
    }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
方式2:单独给参数指定绑定器(无需修改全局配置)

直接在控制器参数上加标记即可:

public IActionResult Test([ModelBinder(typeof(RawRequestBodyModelBinder))] IFormFile file)

步骤3:控制器直接使用入参

现在你原来的控制器逻辑就可以正常运行,不需要手动读取Request.Body:

[HttpPost]
[Consumes("image/png", "image/bmp", System.Net.Mime.MediaTypeNames.Application.Pdf, System.Net.Mime.MediaTypeNames.Image.Tiff)]
[Route("test")]
public IActionResult Test(IFormFile file)
{
    // file已正常赋值,不会为空
    var bitmap = new System.Drawing.Bitmap(file.OpenReadStream());
    bitmap.Save(".\\file.bmp");
    return Ok("Image height: " + bitmap.Height.ToString());
}

注意事项

  • 调用方式和你现在用Postman发送Raw二进制的逻辑完全兼容,不需要修改请求格式,符合不能使用multipart-form的业务限制
  • 如果不需要封装为IFormFile,直接把参数类型改为byte[]或Stream也可以正常绑定

内容的提问来源于stack exchange,提问作者lorenzoKyne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 08:54:03