Returning binary file with httpGet on .Net 6.0 is not returning the file nor the correct headers

1k Views Asked by At

I'm trying to return a firmware file, base on the existing version info that is passed to my HttpGet api via custom headers.

In my ota httpGet I have the following code:

    [HttpGet]
    public HttpResponseMessage OTA()
    {
        var result = new HttpResponseMessage();

        String returnfilename = "c:\\firmware\\device.v0.1h0.2.bin";

        byte[] dataBytes = System.IO.File.ReadAllBytes(returnfilename);

        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 result;
    }

if I call this from Postman I get the following in the Body of the response:

{"version":"1.1","content":{"headers":[{"key":"Content-Length","value":["362688"]},{"key":"Content-Type","value":["application/octet-stream"]},{"key":"Content-Disposition","value":["attachment; filename=firmware.bin"]},{"key":"Content-MD5","value":["QXp/yKD7h6jJzDpG5JyEjw=="]}]},"statusCode":200,"reasonPhrase":"OK","headers":[],"trailingHeaders":[],"requestMessage":null,"isSuccessStatusCode":true}

The actual "Headers" tab in Postman has only 4 headers listed (Which I assume are the actual headers and also explains why my device keeps reporting that the server did not send a Content-Length header):

  • Content-Type: application/json; character=utf-8
  • Date: Wed, 05 Oct 2022 15:11:59 GMT
  • Server: Kestrel
  • Transfer-Encoding: chunked

I'm obviously expecting the json above to be coming back as response headers and also the actual bin file to be sent (which it's not).

What am I doing wrong?

1

There are 1 best solutions below

2
Gineer On BEST ANSWER

So, the answer is that I should have used IActionResult instead of the HttpResponseMessage. Here is the code that works:

    [HttpGet]
    public async Task<IActionResult> OTA()
    {
        String returnfilename = "c:\\firmware\\device.v0.1h0.2.bin";
        if (returnfilename == String.Empty)
        {
            return StatusCode((int)HttpStatusCode.NotModified);
        }

        var stream = System.IO.File.OpenRead(returnfilename);
        return new FileStreamResult(stream, "application/octet-stream");
    }

This method automatically set's all the required headers like Content-Length etc. and the file is actually sent.