.NET 6.0中HttpGet返回二进制文件未返回文件及正确头问题
问题原因
在ASP.NET Core中,直接返回HttpResponseMessage类型对象时,框架会把它当作普通CLR对象做JSON序列化,而非将其作为真实HTTP响应输出。这就是为什么你看到响应体是HttpResponseMessage的JSON结构,自定义响应头、二进制固件内容都没生效,设备自然收不到Content-Length头。
解决方案
推荐用ASP.NET Core原生的结果类型实现需求,以下是几种可行方式:
方式1:用FileContentResult(最简洁)
直接返回FileContentResult,框架会自动处理响应头和二进制内容:
[HttpGet] public IActionResult OTA() { string returnfilename = @"c:\firmware\device.v0.1h0.2.bin"; byte[] dataBytes = System.IO.File.ReadAllBytes(returnfilename); // 计算MD5并转Base64 var md5Hash = MD5.Create().ComputeHash(dataBytes); string md5Base64 = Convert.ToBase64String(md5Hash); // 添加Content-MD5响应头 Response.Headers.Add("Content-MD5", md5Base64); // 返回文件,自动设置Content-Type、Content-Disposition、Content-Length return File(dataBytes, "application/octet-stream", "firmware.bin"); }
方式2:用ResponseMessageResult包装HttpResponseMessage
如果坚持用HttpResponseMessage,需要用ASP.NET Core提供的适配类型包装:
using Microsoft.AspNetCore.Mvc; [HttpGet] public IActionResult OTA() { string returnfilename = @"c:\firmware\device.v0.1h0.2.bin"; byte[] dataBytes = System.IO.File.ReadAllBytes(returnfilename); var result = new HttpResponseMessage(System.Net.HttpStatusCode.OK) { Content = new ByteArrayContent(dataBytes) }; result.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream"); result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = "firmware.bin" }; result.Content.Headers.ContentLength = dataBytes.Length; result.Content.Headers.ContentMD5 = MD5.Create().ComputeHash(dataBytes); return new ResponseMessageResult(result); }
注:如果项目没有相关引用,需要安装Microsoft.AspNetCore.Mvc.WebApiCompatShim包,用于兼容旧Web API特性
方式3:直接操作HttpContext.Response(底层方式)
直接写入响应流,完全控制响应内容:
[HttpGet] public async Task OTA() { string returnfilename = @"c:\firmware\device.v0.1h0.2.bin"; byte[] dataBytes = System.IO.File.ReadAllBytes(returnfilename); var response = HttpContext.Response; response.ContentType = "application/octet-stream"; response.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = "firmware.bin" }.ToString(); response.Headers.ContentLength = dataBytes.Length; response.Headers.ContentMD5 = Convert.ToBase64String(MD5.Create().ComputeHash(dataBytes)); await response.Body.WriteAsync(dataBytes); await response.Body.FlushAsync(); }
额外注意事项
- 路径中的反斜杠要转义,或者用
@符号避免转义问题(比如@"c:\firmware\device.v0.1h0.2.bin") - 确保应用程序有读取
c:\firmware目录文件的权限,否则会触发文件访问异常 - 如果固件文件体积大,别用
File.ReadAllBytes一次性加载到内存,建议用FileStream流式返回,减少内存占用
内容的提问来源于stack exchange,提问作者Gineer
相关产品推荐
相关产品推荐

