3

I have small local web server based on HttpListener. The server provides files to local client application unpacking and writing files to

response.OutputStream;

but sometimes files (videos) are huge and I don't think it's a good idea to always copy all file bytes to output stream (memory). I would like to connect served file stream to response output stream something like this:

response.OutputStream = myFileStream;

but -ok- response.OutputStream is read only so I just can write bytes - is there any way to make some kind of partial writing (streaming)?

Regards.

Przemysław Michalski
  • 9,627
  • 7
  • 31
  • 37
  • 1
    so... you are trying to create a streaming connection, next step will be to divide the file to seperate packages and send them all simultaneously and reconstruct them at the client-side... why won't you just do that? – No Idea For Name Aug 02 '13 at 08:08
  • Served video files are displayed in web browser (gecko fx) and when video (mp4) request comes (html5 – Przemysław Michalski Aug 02 '13 at 08:16

1 Answers1

2

You will need to create a thread and stream your data to response. Use something like this:

in your main thread:

while (Listening)
{
    // wait for next incoming request
    var result = listener.BeginGetContext(ListenerCallback, listener);
    result.AsyncWaitHandle.WaitOne();
}

somewhere in your class:

public static void ListenerCallback(IAsyncResult result)
{
    var listenerClosure = (HttpListener)result.AsyncState;
    var contextClosure = listenerClosure.EndGetContext(result);

    // do not process request on the dispatcher thread, schedule it on ThreadPool
    // otherwise you will prevent other incoming requests from being dispatched
    ThreadPool.QueueUserWorkItem(
        ctx =>
        {
            var response = (HttpListenerResponse)ctx;

            using (var stream = ... )
            {
                stream.CopyTo(response.ResponseStream);
            }

            response.Close();
        }, contextClosure.Response);
}
Roman Polunin
  • 53
  • 3
  • 12
  • 1
    Here's a similar post (has more context): http://stackoverflow.com/questions/13385633/serving-large-files-with-c-sharp-httplistener?rq=1 – Roman Polunin Nov 08 '13 at 21:46
  • 1
    I think that stream.CopyTo(response.ResponseStream) copy all file bytes to output stream and this is what I want to avoid. – Przemysław Michalski Feb 13 '14 at 19:24
  • 1
    UGEEN, if you set .AllowWriteStreamBuffering property to false, it will not cache anything locally. It will stop sending when client stops receiving. – Roman Polunin Feb 13 '14 at 21:50
  • Thank you for your response. I have HttpListener in my case and HttpListenerResponse. I would like to stream video file data to WebBrowser video tag (html5) - is there any way to set AllowWriteStreamBuffering in this case - I didn't found the way and after hours of seraching give up:-) – Przemysław Michalski Feb 17 '14 at 07:48
  • Ouch.. that property is on the Request, client-side. I somehow assumed that you were streaming data to server, e.g. uploading it. – Roman Polunin Feb 17 '14 at 19:16
  • 1
    Well, normally if you don't want to send everything from server, you need to expect client to tell you what exactly it needs. For video, there may be special conventions - but for regular data, clients usually attach 'content-range' header in which you can expect to receive the range of bytes that client wants to get in response to this particular request. Look here: http://stackoverflow.com/questions/716680/difference-between-content-range-and-range-headers – Roman Polunin Feb 17 '14 at 19:18
  • 1
    Also, keep in mind that even though CopyTo will send everything, it won't attempt to cache that data in server memory first. HttpListener's response implementation also does not cache sent data. – Roman Polunin Feb 17 '14 at 19:21
  • Thank you very much for your answers - it helps to understand the nature of the problem. – Przemysław Michalski Feb 18 '14 at 08:50