DevelopedLogic
DevelopedLogic

Reputation: 165

Sending a PNG using HTTP in C#

I'm developing my own simple webserver in C#, and I have normal html files and subfolders etc in place and working fine... however my issue lies with sending PNG files.

Once the browser has made the HTTP request and my other code has done its magic, I need to send a response header. Here is my code to do this:

        else if (URL.EndsWith(".ico") || URL.EndsWith(".png"))
        {
            if (File.Exists(Program.Start_Directory + URL))
            {
                byte[] ImgFile = File.ReadAllBytes(Program.Start_Directory + URL);
                sw.Write("HTTP/1.0 200 OK\r\n");
                sw.Write("Content-Type: image/png\r\n");
                sw.Write("Content-Length: " + ImgFile.Length + "\r\n");
                sw.Write("\r\n");
                sw.Write(ImgFile);
            }
            else
            {
                FileNotFoundPage(sw);
            }
        }

sw in this instance being the StreamWriter for the socket connection to the browser.

When I run this, the browser screen goes black like it usually does when its about to load an image, but no image loads and the spinning loading wheel remains spinny indefinitely.

How can I get this to work? Thanks.

Upvotes: 1

Views: 1182

Answers (1)

spender
spender

Reputation: 120410

Things get messy when you use a StreamWriter (which is designed to write strings with a specific Encoding to a stream) with binary data.

It looks like you are invoking this overload of StreamWriter.Write with the belief that it writes the bytes verbatim to the output stream. The docs state that this overload actually...

Writes the text representation of an object to the text string or stream by calling the ToString method on that object

You have two options. Carry on using StreamWriter and Flush, then write the binary data directly to the underlying stream:

byte[] ImgFile = File.ReadAllBytes(Program.Start_Directory + URL);
sw.Write("HTTP/1.0 200 OK\r\n");
//...etc
sw.Flush();
sw.BaseStream.Write(ImgFile,0,ImgFile.Length);

or just do everything in bytes:

var sb=new StringBuilder();
sb.AppendLine("HTTP/1.0 200 OK");
//...etc
var headerBytes = Encoding.ASCII.GetBytes(sb.ToString());
Stream str = iGotTheStreamFromSomewhere;
str.Write(headerBytes,0,headerBytes.Length);
str.Write(ImgFile,0,ImgFile.Length);

Upvotes: 1

Related Questions