16

I have a small HTTP-Server here written in C# and until now I only needed to send raw text back to the sender. But now I have to send a JPG-Image and I dont unterstand how.

this is what I have now:

// Read the HTTP Request
Byte[] bReceive = new Byte[MAXBUFFERSIZE];
int i = socket.Receive(bReceive, bReceive.Length, 0);

//Convert Byte to String
string sBuffer = Encoding.ASCII.GetString(bReceive);

// Look for HTTP request
iStartPos = sBuffer.IndexOf("HTTP", 1);

// Extract the Command without GET_/ at the beginning and _HTTP at the end
sRequest = sBuffer.Substring(5, iStartPos - 1 - 5);
String answer = handleRequest(sRequest);


// Send the response
socket.Send(Encoding.UTF8.GetBytes(answer));

I think I have to do some kind of filestream instead of a string but I really have no glue..

Pieter van Ginkel
  • 29,160
  • 8
  • 71
  • 111
martinyyyy
  • 1,652
  • 3
  • 21
  • 44
  • Can you post a portion of your handleRequest method? I'm guessing that's where you're building the HTTP Response object that will be sent back to the browser making the request. You'll have to figure out how to modify that to support images. – Justin Niessner Nov 11 '10 at 13:43
  • 1
    I have some glue if you want to borrow it :/ – Jeff LaFay Nov 11 '10 at 13:53
  • @Martin if you are reading from file you can just call socket.SendFile . see here(msdn.microsoft.com/en-us/library/sx0a40c2.aspx – Arsen Mkrtchyan Nov 11 '10 at 13:58

2 Answers2

2

Do you want to send from file or Bitmap object?

MemoryStream myMemoryStream = new MemoryStream();
myImage.Save(myMemoryStream);
myMemoryStream.Position = 0;

EDIT

// Send the response
SendVarData(socket,memoryStream.ToArray());

for sending MemoryStream by socket you can use this method given here

 private static int SendVarData(Socket s, byte[] data)
 {
            int total = 0;
            int size = data.Length;
            int dataleft = size;
            int sent;

            byte[] datasize = new byte[4];
            datasize = BitConverter.GetBytes(size);
            sent = s.Send(datasize);

            while (total < size)
            {
                sent = s.Send(data, total, dataleft, SocketFlags.None);
                total += sent;
                dataleft -= sent;
            }
            return total;
 }
Community
  • 1
  • 1
Arsen Mkrtchyan
  • 49,896
  • 32
  • 148
  • 184
  • Ehh. Are there really a Send overload taking a stream? – jgauffin Nov 11 '10 at 13:35
  • @jgauffin - socket.SendFile() would be the option if you were only interested in sending the file. This will not, though, provide any of the proper HTTP Response Formatting that is required for a proper response. – Justin Niessner Nov 11 '10 at 13:38
  • that's not what I asked :) AFAIK there are no overload taking a stream as an argument. – jgauffin Nov 11 '10 at 13:45
  • Why not let the SendVarData take a Stream as an argument instead? Seems a bit more memory effecient. – jgauffin Nov 11 '10 at 13:47
  • 1
    if you are reading from file you can just call socket.SendFile . see here(http://msdn.microsoft.com/en-us/library/sx0a40c2.aspx) – Arsen Mkrtchyan Nov 11 '10 at 13:55
2

Why did you create a httpserver by yourself? Why not use a open source one? For instance mine: http://webserver.codeplex.com

public class Example    
{
    private HttpListener _listener;

    public void StartTutorial()
    {
        _listener = HttpListener.Create(IPAddress.Any, 8081);
        _listener.RequestReceived += OnRequest;
        _listener.Start(5);
    }

    private void OnRequest(object source, RequestEventArgs args)
    {
        IHttpClientContext context = (IHttpClientContext)source;
        IHttpRequest request = args.Request;

        IHttpResponse response = request.CreateResponse(context);
        response.Body = new FileStream("Path\\to\\file.jpg");
        response.ContentType = "image\jpeg";
        response.Send();
    }

}

Edit

If you really want do do it by yourself:

string responseHeaders = "HTTP/1.1 200 The file is coming right up!\r\n" +
"Server: MyOwnServer\r\n" +
"Content-Length: " + new FileInfo("C:\\image.jpg").Length + "\r\n" +
"Content-Type: image/jpeg\r\n" + 
"Content-Disposition: inline;filename=\"image.jpg;\"\r\n" +
"\r\n";

//headers should ALWAYS be ascii. Never UTF8
var headers = Encoding.ASCII.GetBytes(responseHeaders); 
socket.Send(headers, 0, headers.Length);
socket.SendFile("C:\\image.jpg");
jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • because it's a really simple one and it doesn't act like a HTTP Server.. I only recieve commands example: http://localhost/winamp.play – martinyyyy Nov 11 '10 at 13:49
  • Really? Show me a http server which can be embedded in a .Net 2.0 application. The .Net HttpListener requires administration privileges to be able to subscribe on certain uris. Not very flexible. My point was that if you don't have enough HTTP knowledge you'll probably going to waste a lof time trying to get stuff work. It should be more effecient to use existing libraries. – jgauffin Nov 11 '10 at 13:54
  • 1
    Maybe their intent is to gather knowledge about HTTP and C#? Not everything is done for productivity. – Christoph Böhmwalder May 12 '15 at 07:33
  • @HackerCow: Isn't the best way to lean to read an actual implementation? – jgauffin May 12 '15 at 08:18
  • 3
    No, the best way to learn a protocol is to implement is and the best way to learn a language is to implement something in it (at least that holds true for me) – Christoph Böhmwalder May 12 '15 at 08:40
  • Where in his question do he ever mention the protocol or ask for the correct way to do it in HTTP? His question is about how to do it on a network level. Learning both HTTP and network programming is not a small task, hence my suggestion to use something which is already available. My assumption is just as valid as yours as we both ***guess*** want his ultimate goal is. But as his question is about how to do it on the network level my answer is better since it actually show how to do it with a complete code solution. – jgauffin May 12 '15 at 08:44