Download file from controller

Navaneeth picture Navaneeth · Jan 5, 2016 · Viewed 11.5k times · Source

In Aspnet5 RC1 update1 web application, trying to do same as Response.BinaryWrite, file download in old AspNet application. User needs to get a popup save dialog in client side.

when the following code is used, a popup prompt appears in client side to save the file.

public void Configure(IApplicationBuilder app)
{
    //app.UseIISPlatformHandler();
    //app.UseStaticFiles();
    //app.UseMvc();
    app.Run(async (objContext) =>
    {
        var cd = new System.Net.Mime.ContentDisposition { 
                     FileName = "test.rar", Inline = false };
        objContext.Response.Headers.Add("Content-Disposition", cd.ToString());
        byte[] arr = System.IO.File.ReadAllBytes("G:\\test.rar");
        await objContext.Response.Body.WriteAsync(arr, 0, arr.Length);
    });
}

But when the same code is used inside a Controller's action, app.Run is commented out, save popup does not appear, the content is just rendered as text.

[Route("[controller]")]
public class SampleController : Controller
{
    [HttpPost("DownloadFile")]
    public void DownloadFile(string strData)
    {
        var cd = new System.Net.Mime.ContentDisposition { 
                     FileName = "test.rar", Inline = false };                
        Response.Headers.Add("Content-Disposition", cd.ToString());
        byte[] arr = System.IO.File.ReadAllBytes("G:\\test.rar");                
        Response.Body.WriteAsync(arr, 0, arr.Length);  

The need is, control flow needs to come to controller, perform some logic , then send byte[] response content to client side, user needs to save the file. There is no cshtml, just plain html with jquery ajax call.

Answer

Oleg picture Oleg · Jan 5, 2016

Do you really need HttpPost attribute? Try to remove it or to use HttpGet instead:

public async void DownloadFile()
{
    Response.Headers.Add("content-disposition", "attachment; filename=test.rar");
    byte[] arr = System.IO.File.ReadAllBytes(@"G:\test.rar");
    await Response.Body.WriteAsync(arr, 0, arr.Length);
}

UPDATED: Probably more easy would be the usage of FileStreamResult:

[HttpGet]
public FileStreamResult DownloadFile() {
    Response.Headers.Add("content-disposition", "attachment; filename=test.rar");
    return File(new FileStream(@"G:\test.rar", FileMode.Open),
                "application/octet-stream"); // or "application/x-rar-compressed"
}