dumbledad
dumbledad

Reputation: 17535

Passing bytes through Web API: why are these files different?

I'm storing bitmap images in an Azure blob store and delivering them to a .Net Micro Framework device. Because of memory limitations on the device I need to break the files into chunks and deliver them to the device where they are to be recombined onto the device's microSD card. I am having trouble with byte fidelity and am struggling to understand this pared down test.

I have a simple bitmap on azure: https://filebytetest9845.blob.core.windows.net/files/helloworld.bmp It is just a black and white bitmap of the words "Hello World".

Here's some test code I've written to sit in an ASP .Net Web API and read the bytes ready for breaking into chunks. But to test I just store the bytes to a local file.

[Route("api/testbytes/")]
[AcceptVerbs("GET", "POST")]
public void TestBytes()
{
    var url = "https://filebytetest9845.blob.core.windows.net/files/helloworld.bmp";
    var fileRequest = (HttpWebRequest) WebRequest.Create(url);
    var fileResponse = (HttpWebResponse) fileRequest.GetResponse();
    if (fileResponse.StatusCode == HttpStatusCode.OK)
    {
        if (fileResponse.ContentLength > 0)
        {
            var responseStream = fileResponse.GetResponseStream();
            if (responseStream != null)
            {
                var contents = new byte[fileResponse.ContentLength];
                responseStream.Read(contents, 0, (int) fileResponse.ContentLength);
                if (!Directory.Exists(@"C:\Temp\Bytes\")) Directory.CreateDirectory(@"C:\Temp\Bytes\");
                using (var fs = System.IO.File.Create(@"C:\Temp\Bytes\helloworldbytes.bmp"))
                {
                    fs.Write(contents, 0, (int) fileResponse.ContentLength);
                }
            }
        }
    }
}

Here's the original bitmap:

original bitmap

And here's the version saved to disk:

saved bitmap

As you can see they are different, but my code should just be saving a byte-for-byte copy. Why are they different?

Upvotes: 0

Views: 929

Answers (2)

Norfolc
Norfolc

Reputation: 458

Atomosk is right - single Read call can't read whole response. If you are using .NET 4+, then you can use this code to read full response stream:

        var fileResponse = (HttpWebResponse)fileRequest.GetResponse();
        if (fileResponse.StatusCode == HttpStatusCode.OK)
        {
            var responseStream = fileResponse.GetResponseStream();
            if (responseStream != null)
            {
                using (var ms = new MemoryStream())
                {
                    responseStream.CopyTo(ms);
                    ms.Position = 0;
                    using (var fs = System.IO.File.Create(@"C:\Temp\Bytes\helloworldbytes.bmp"))
                    {
                        ms.CopyTo(fs);
                    }
                }
            }
        }

Using this code you don't need to know Content Length since it is not always available.

Upvotes: 1

Atomosk
Atomosk

Reputation: 2017

Try this

var contents = new byte[fileResponse.ContentLength];
int readed = 0;
while (readed < fileResponse.ContentLength)
{
    readed += responseStream.Read(contents, readed, (int)fileResponse.ContentLength - readed);
}

looks like it can't download whole image in single Read call and you have to recall it untill whole image is downloaded.

Upvotes: 1

Related Questions