Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

adding header to http response in an action inside a controller in asp.net/mvc

I am streaming data from server to client for download using filestream.write. In that case what is happening is that I am able to download the file but it does not appear as download in my browser. Neither the pop-up for "Save As" appears not "Download Bar" appears in Downloads section. From looking around, I guess I need to include "something" in the response header to tell the browser that there is an attachment with this response. Also I want to set the cookie. To accomplish this, this is what I am doing:

        [HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=" & name)]
    public ActionResult Download(string name)
    {
          // some more code to get data in inputstream.

          using (FileStream fs = System.IO.File.OpenWrite(TargetFile))
            {
                byte[] buffer = new byte[SegmentSize];
                int bytesRead;
                while ((bytesRead = inputStream.Read(buffer, 0, SegmentSize)) > 0)
                {
                    fs.WriteAsync(buffer, 0, bytesRead);
                }
            }
        }
        return RedirectToAction("Index");
    }

I am getting error that: "System.web.httpcontext.current is a property and is used as a type."

Am I doing the header updating at the right place? Is there any other way to do this?

like image 794
ezile Avatar asked Apr 18 '13 23:04

ezile


2 Answers

Yes, You are doing it the wrong way try this, you should add the header inside your action not as an attribute header to your method.

HttpContext.Current.Response.AppendHeader("Content-Disposition","attachment;filename=" & name)

or

Request.RequestContext.HttpContext.Response.AddHeader("Content-Disposition", "Attachment;filename=" & name)

Update As i understand you are making an ajax call to your controller/action which wont work for file download by directly calling an action. You can achieve it this way.

public void Download(string name)
        {
//your logic. Sample code follows. You need to write your stream to the response.

            var filestream = System.IO.File.ReadAllBytes(@"path/sourcefilename.pdf");
            var stream = new MemoryStream(filestream);
            stream.WriteTo(Response.OutputStream);
            Response.AddHeader("Content-Disposition", "Attachment;filename=targetFileName.pdf");
            Response.ContentType = "application/pdf";
        }

or

    public FileStreamResult Download(string name)
    {
        var filestream = System.IO.File.ReadAllBytes(@"path/sourcefilename.pdf");
        var stream = new MemoryStream(filestream);


        return new FileStreamResult(stream, "application/pdf")
        {
            FileDownloadName = "targetfilename.pdf"
        };
    }

In your JS button click you can just do something similar to this.

 $('#btnDownload').click(function () {
            window.location.href = "controller/download?name=yourargument";
    });
like image 138
PSL Avatar answered Nov 09 '22 01:11

PSL


Please take a look here.

Following is taken from referenced website.

public FileStreamResult StreamFileFromDisk()
{
    string path = AppDomain.CurrentDomain.BaseDirectory + "uploads/";
    string fileName = "test.txt";
    return File(new FileStream(path + fileName, FileMode.Open), "text/plain", fileName);
}

Edit 1:

Adding something that might be more of your interest from our good ol' SO. You can check for complete detail here.

public ActionResult Download()
{
    var document = ...
    var cd = new System.Net.Mime.ContentDisposition
    {
        // for example foo.bak
        FileName = document.FileName, 

        // always prompt the user for downloading, set to true if you want 
        // the browser to try to show the file inline
        Inline = false, 
    };
    Response.AppendHeader("Content-Disposition", cd.ToString());
    return File(document.Data, document.ContentType);
}
like image 38
Abhinav Avatar answered Nov 09 '22 00:11

Abhinav