The HttpListener returns an audio file to play in the browser.

I am using the HttpListener class to create a very simple web server.

I can serve html, javascript, attachments, probably everything to the browser. The only thing I get is to provide the browser with a wav file for it to play.

The file I want to play in the browser is the following: https://dl.dropboxusercontent.com/u/81397375/a.wav

Please note that if you click on this link, your browser will start playing the audio file instead of downloading it as an attachment. I want to do the same with the HttpListerner class!

Anyway, here's my code:

string pathToMyAudioFile = @"c:\a.wav";

// create web server
var web = new HttpListener();

// listen on port 8081 only on local connections for testing purposes
web.Prefixes.Add("http://localhost:8081/");

Console.WriteLine(@"Listening...");

web.Start();

// run web server forever
while (true)
{
    var context = web.GetContext();

    var requestUrl = context.Request.Url.LocalPath.Trim('/');

    // this command will stop the web server
    if (requestUrl == "Stop")
    {
        context.Response.StatusCode = 200; // set response to ok
        context.Response.OutputStream.Close();
        break; 
    }
    else if (requestUrl == "DownloadAudio") // <--------- here is where I am interested
    {
        // we are ready to give audio file to browser
        using (var fs = new FileStream(pathToMyAudioFile , FileMode.Open))
        {
            context.Response.ContentLength64 = fs.Length;
            context.Response.SendChunked = true;
            //obj.Response.ContentType = System.Net.Mime.MediaTypeNames.Application.Octet;
            context.Response.ContentType = "audio/wav";

            //obj.Response.AddHeader("Content-disposition", "attachment; filename=" + fs.Name);
            context.Response.StatusCode = 206; // set to partial content

            byte[] buffer = new byte[64 * 1024];

            try
            {
                using (BinaryWriter bw = new BinaryWriter(context.Response.OutputStream))
                {
                    int read;
                    while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                    {

                        bw.Write(buffer, 0, read);
                        bw.Flush(); //seems to have no effect
                    }

                    bw.Close();
                }
            }
            catch
            {
                Console.Write("closded connection");
            }
        }
    }
    else
    {
        context.Response.StatusCode = 404; // set response to not found
    }

    // close output stream
    context.Response.OutputStream.Close();
}

web.Stop();

      

Now when I go to http://localhost:8081/DownloadAudio

I see the following:

enter image description here

But I cannot play the file. Why? What headers am I missing? I don't want to download the file as an attachment.


Decision

I found a solution. I'm missing a title Content-Range

. This is what the response looks like when it reappears on a real IIS web server:

enter image description here

Notice how it specifies the ranges that it sends with a header: Content-Range: bytes 0-491515/491516

So I just need to add the line

context.Response.Headers.Add("Content-Range", $"bytes 0-{fs.Length-1}/{fs.Length}");

      

Into my code and now it works! If the audio file is very large, I could do some math, so I don't return everything at once.

+3


source to share





All Articles