0

I've created a simple controller for uploading and getting a (static) cached image. I know it's not the best practice to have a static byte array but it's just for test purposes.

It works as expected except there's always about 60-80% data missing from the image when I'm trying to download it.

[Route("image")]
public class CameraController : ControllerBase
{
    private static byte[] latestImageData;

    [HttpPost("upload")]
    public async Task<ActionResult> PostData()
    {
        if(HttpContext.Request.ContentType == "image/jpeg")
        {
            var contentLength = Convert.ToInt32(HttpContext.Request.ContentLength);

            latestImageData = new byte[contentLength];
            await HttpContext.Request.Body.ReadAsync(latestImageData);
        }

        return NoContent();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    [HttpGet("get")]
    public ActionResult GetImage()
    {
        if (latestImageData != null)
        {

            return File(latestImageData, "image/jpeg");
        }
        else
            return NoContent();
    }
}

This is the result I'm getting when I'm trying to download the image: Screenshot from Chrome

Any ideas?

ProgrammingLlama
  • 36,677
  • 7
  • 67
  • 86
Felix
  • 138
  • 2
  • 11
  • 3
    `ReadAsync` will read _up to_ `contentLength` bytes. It will return the number of bytes it read. [Documented here](https://learn.microsoft.com/en-us/dotnet/api/system.io.stream.readasync?view=net-5.0#System_IO_Stream_ReadAsync_System_Memory_System_Byte__System_Threading_CancellationToken_): _"The value of its Result property contains the total number of bytes read into the buffer. **The result value can be less than the number of bytes allocated in the buffer if that many bytes are not currently available**, or it can be 0 (zero) if the end of the stream has been reached."_ – ProgrammingLlama Sep 08 '21 at 08:55
  • @Llama Okay, how do I make them available to read? Why aren't they available? – Felix Sep 08 '21 at 09:52
  • 1
    @Felix There are something wrong with your `latestImageData`. Usually I upload file by form-data, not binary. You can try it. – Jason Pan Sep 08 '21 at 10:03
  • 1
    You could use Jon Skeet's method in [this answer](https://stackoverflow.com/a/221941/3181933) as a quick and dirty solution. Or this [alternative answer](https://stackoverflow.com/a/6586039/3181933). Be aware you can replace `Read` and `CopyTo` with `await ReadAsync` and `await CopyToAsync` to make use of the async/await pattern. – ProgrammingLlama Sep 08 '21 at 10:09
  • @JasonPan I'm receiving data from another application so I can't change that unfortunately. – Felix Sep 08 '21 at 11:49
  • @Llama That did the trick, thank you! – Felix Sep 08 '21 at 11:50

1 Answers1

0

Found the answer to my problem from this answer, thanks to Llama in the comments.

    [HttpPost("upload")]
    public async Task<ActionResult> PostData()
    {
        if(HttpContext.Request.ContentType == "image/jpeg")
        {
            using (var ms = new MemoryStream())
            {
                await HttpContext.Request.Body.CopyToAsync(ms);

                latestImageData = ms.ToArray();
            }
        }

        return NoContent();
    }
Felix
  • 138
  • 2
  • 11