Returning binary file from controller in ASP.NET Web API

asp.net, asp.net-mvc, asp.net-web-api

Solution

Try using a simple `HttpResponseMessage` with its `Content` property set to a `StreamContent`:

// using System.IO;
// using System.Net.Http;
// using System.Net.Http.Headers;

public HttpResponseMessage Post(string version, string environment,
    string filetype)
{
    var path = @"C:\Temp\test.exe";
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = 
        new MediaTypeHeaderValue("application/octet-stream");
    return result;
}

A few things to note about the `stream` used:

You must not call `stream.Dispose()`, since Web API still needs to be able to access it when it processes the controller method's `result` to send data back to the client. Therefore, do not use a `using (var stream = …)` block. Web API will dispose the stream for you.

Make sure that the stream has its current position set to 0 (i.e. the beginning of the stream's data). In the above example, this is a given since you've only just opened the file. However, in other scenarios (such as when you first write some binary data to a `MemoryStream`), make sure to `stream.Seek(0, SeekOrigin.Begin);` or set `stream.Position = 0;`

With file streams, explicitly specifying `FileAccess.Read` permission can help prevent access rights issues on web servers; IIS application pool accounts are often given only read / list / execute access rights to the wwwroot.

Problem

I'm working on a web service using ASP.NET MVC's new WebAPI that will serve up binary files, mostly `.cab` and `.exe` files. The following controller method seems to work, meaning that it returns a file, but it's setting the content type to `application/json`: ``` public HttpResponseMessage<Stream> Post(string version, string environment, string filetype) { var path = @"C:\Temp\test.exe"; var stream = new FileStream(path, FileMode.Open); return new HttpResponseMessage<Stream>(stream, new MediaTypeHeaderValue("application/octet-stream")); } ``` Is there a better way to do this?

Original source

Related problems