54

I have an MVC project that will display some documents to users. The files are currently stored in Azure blob storage.

Currently, the documents are retrieved from the following controller action:

[GET("{zipCode}/{loanNumber}/{classification}/{fileName}")]
public ActionResult GetDocument(string zipCode, string loanNumber, string classification, string fileName)
{
    // get byte array from blob storage
    byte[] doc = _docService.GetDocument(zipCode, loanNumber, classification, fileName);
    string mimeType = "application/octet-stream";
    return File(doc, mimeType, fileName);
}

Right now, when a user clicks on a link like the following:

<a target="_blank" href="http://...controller//GetDocument?zipCode=84016&loanNumber=12345678classification=document&fileName=importantfile.pdf

Then, the file downloads to their browser's downloads folder. What I would like to happen (and I thought was default behavior) is for the file to simply be displayed in the browser.

I have tried changing the mimetype and changing the return type to FileResult instead of ActionResult, both to no avail.

How can I make the file display in the browser instead of downloading?

tereško
  • 58,060
  • 25
  • 98
  • 150
Trevor
  • 2,138
  • 1
  • 16
  • 31
  • 3
    Pretty sure the browser decides how to handle the file based on the mimeType. http://www.webmaster-toolkit.com/mime-types.shtml – Tommy Oct 16 '13 at 19:04
  • That's what I suspected too, so I tried various mimetypes associated with .pdf's and attempted to open the file, but it downloaded each time. When I view other pdf's on other sites they open in the browser window. – Trevor Oct 16 '13 at 19:08
  • 2
    What's the value of the content-disposition header? – Ian McLaird Oct 16 '13 at 19:11
  • Header Response: Content-Disposition:attachment; filename=importantfile.pdf – Trevor Oct 16 '13 at 19:18
  • 1
    Yep. That's your problem. – Ian McLaird Oct 16 '13 at 19:19

4 Answers4

99

Thanks to all the answers, the solution was a combination of all of them.

First, because I was using a byte[] the controller action needed to be FileContentResult not just FileResult. Found this thanks to: What's the difference between the four File Results in ASP.NET MVC

Second, the mime type needed to NOT be a octet-stream. Supposedly, using the stream causes the browser to just download the file. I had to change the type application/pdf. I will need to explore a more robust solution to handle other file/mime types though.

Third, I had to add a header that changed the content-disposition to inline. Using this post I figured out I had to modify my code to prevent duplicate headers, since the content-disposition was already being set to attachment.

The successful code:

public FileContentResult GetDocument(string zipCode, string loanNumber, string classification, string fileName)
{
    byte[] doc = _docService.GetDocument(zipCode, loanNumber, classification, fileName);
    string mimeType = "application/pdf"
    Response.AppendHeader("Content-Disposition", "inline; filename=" + fileName);
    return File(doc, mimeType);
} 
Community
  • 1
  • 1
Trevor
  • 2,138
  • 1
  • 16
  • 31
  • 23
    More robust solution for getting mimetype: `return File(doc, MimeMapping.GetMimeMapping(fileName));` – Trevor Oct 16 '13 at 21:06
  • 1
    Awesome you got it solved. The link I put in the comment above will allow you to create a dictionary based on file extensions for MimeTypes. Then, just create a static function that takes a file extension and returns a MIME type for any file you are expecting (I probably wouldn't cover .crt for instance). If an extension is not found, return the standard *application/octet-stream* – Tommy Oct 16 '13 at 21:53
  • 1
    Worked like a charm! Best solution. – Khateeb321 Apr 16 '17 at 17:03
  • _More robust solution_ really works, wouldn't it need to be placed/edited in the the main answer.. ?? – Irf Feb 05 '18 at 12:10
  • Do the files being displayed in the browser window leave a footprint in the file system of the client or the server? I have Personally Identifiable Info on the files i'm displaying and I need to make sure that the viewed file is not viewable outside of the web application – jplara May 29 '20 at 19:44
  • @jplara I don't think you can do that. If it's a native app you may be able to restrict it, but otherwise you'll need a wrapper of some sort. It's a PDF in the answer so if the browser opens it, the user can choose to save it, copy from it, etc. I do have a similar issue, but the risk is the automatic downloading of unwanted/unknown copies of that personal data to multiple client machines, not the risk of the user deliberately saving it, which actually may be required at times. – Sam_Butler Aug 06 '20 at 15:26
  • As soon as i specify a file name, the file will be downloaded instead of previewing in browser. Firefox is the only exception, as far as i know, which gives user a choise whether to show or download the file. The name must be specified if dynamic mimetype is used to avoid strange names or extensions. – Painkiller Dec 16 '20 at 12:15
17

It looks like someone else asked a similar question a while ago:

how to force pdf files to open in a browser

With an answer saying that you should use the header:

Content-Disposition: inline; filename.pdf
Community
  • 1
  • 1
welegan
  • 3,013
  • 3
  • 15
  • 20
  • Ok, so unfortunately I tried this, and had to follow the steps in the linked post, but it still does not work. I tried changing the return type to FileContentResult and that also did not help. – Trevor Oct 16 '13 at 19:35
  • 1
    This was definitely part of the solution, thank you! – Trevor Oct 16 '13 at 20:09
4

Browsers should decide on downloading or displaying based on mime-type.

Try this:

string mimeType = "application/pdf";
Andre Pena
  • 56,650
  • 48
  • 196
  • 243
0

Just return PhysicalFileResult and use HttpGet method ,url will open pdf file

public ActionResult GetPublicLink()
{
     path = @"D:\Read\x.pdf";
    return new PhysicalFileResult(path, "application/pdf");
}
Divya
  • 373
  • 4
  • 3