【问题标题】:.NET Core HttpClient upload byte array gives unsupported media type error.NET Core HttpClient 上传字节数组给出不支持的媒体类型错误
【发布时间】:2020-10-06 12:36:12
【问题描述】:

我正在尝试为我的 Web Api 控制器 (ASP.NET Core 3) 上传一个简单的字节数组

using var client = new HttpClient() { BaseAddress = new Uri("http://someUrl.com/") };
var body = new ByteArrayContent(new byte[] {1, 2, 3});

var result = await client.PostAsync("api/somecontroller/content?someField=someData", body);

控制器

[HttpPost("content")]
public IActionResult Upload([FromBody]byte[] documentData, [FromQuery] string someField)
{
    ...

    return Ok();
}

但这给了我错误415 Unsupported media type。为什么 ?我需要在 url 中添加一些额外的数据,但我认为这不是问题所在。

【问题讨论】:

  • 试试这个:在接收端,删除主体参数并在请求主体上使用流:MemoryStream stream =new MemoryStream((int)Request.Body.Length); await Request.Body.CopyToAsync(stream); byte[] byteArray = stream.ToArray();
  • 另外,您可以尝试在此答案中设置内容标题:stackoverflow.com/a/23884972/479251

标签: c# asp.net-core


【解决方案1】:

请注意,上面的答案有错别字,这可能会花费您很多时间(gif文件中的代码不正确,可能会产生损坏的不完整字节数组):

public async override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        var stream = new MemoryStream();
        await context.HttpContext.Request.Body.CopyToAsync(stream);
        return InputFormatterResult.Success(stream.ToArray());
    }

【讨论】:

    【解决方案2】:

    虽然byte[] 是表示application/octet-stream 数据的好方法,但在 asp.net 核心 Web API 中默认情况下并非如此。

    这是一个简单的解决方法:

    通过 HttpClient 发送请求:

    using var client = new HttpClient() { BaseAddress = new Uri("http://localhost:62033") };
    var body = new ByteArrayContent(new byte[] { 1, 2, 3 });
    body.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");           
    var result = await client.PostAsync("api/Values/content?someField=someData", body);
    

    在 Web Api 项目中接收操作:

    [HttpPost("content")]
    public IActionResult Upload([FromBody]byte[] documentData, [FromQuery] string someField)
    {
            return Ok();
    }
    

    Web Api 项目中的自定义 InputFormatter:

    public class ByteArrayInputFormatter : InputFormatter
    {
        public ByteArrayInputFormatter()
        {
            SupportedMediaTypes.Add(Microsoft.Net.Http.Headers.MediaTypeHeaderValue.Parse("application/octet-stream"));
        }
    
        protected override bool CanReadType(Type type)
        {
            return type == typeof(byte[]);
        }
    
        public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            var stream = new MemoryStream();
            await context.HttpContext.Request.Body.CopyToAsync(stream);
            return InputFormatterResult.SuccessAsync(stream.ToArray());
        }
    }
    

    Web Api 项目中的 Startup.cs:

    services.AddControllers(options=> 
            options.InputFormatters.Add(new ByteArrayInputFormatter()));
    

    结果:

    【讨论】:

    • 您能异步/等待 ReadRequestBodyAsync 方法吗?我在我的代码中想到了一些问题,因此浪费了 20 分钟。
    • 注意“Request.Body.CopyToAsync”没有被等待,所以每次运行你都可以获得输入流的不同部分!最好在函数上使用 async 并等待 copyasync ..
    • 其中一种方法似乎有几个错别字。它应该是 public async override Task ReadRequestBodyAsync(InputFormatterContext context) { var stream = new MemoryStream();等待 context.HttpContext.Request.Body.CopyToAsync(stream);返回等待 InputFormatterResult.SuccessAsync(stream.ToArray()); }
    【解决方案3】:

    问题是由仅支持简单类型的 [FromBody] 属性引起的。您可以将Type Converters 用于其他类型。正确的控制器动作代码应该是:

        [HttpPost("content")]
        public IActionResult content([FromQuery] string someField)
        {
            var documentData= new byte[Request.ContentLength.Value];
             Request.Body.ReadAsync(documentData);
            //...
            return Ok();
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 2019-08-23
      相关资源
      最近更新 更多