Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve a file in MVC without exposing the URL?

I have a tree-viewer which allows for the user to browse files and sub-directories, when the user reaches a file, the website will go to https://website.com/path/subpath/file.pdf. Assuming I can identify that the user is viewing a file, the following will happen:

  • The controller will generate a SAS key to retrieve the file from Azure.
  • The controller will get a url: https://myaccount.files.core.windows.net/path/?=accesskey

While there is no problem with the user viewing this access key, it will eventually expire, and for the user to bookmark the page, I would like the user not to be redirected to the Azure path, but for ASP.NET to output the file as if the user is still at https://website.com/path/subpath/file.pdf

So the end question is basically:

How can I output a file, without forcing download and without showing the file path/url?

like image 442
devSparkle Avatar asked Dec 24 '15 18:12

devSparkle


1 Answers

You may try to read the file from your storage as a byte array and use the File method to return it from the action method.

public ActionResult View(int id)
{
  // id is a unique id for the file. Use that to get the file from your storage.
  byte[] byteArrayOfFile=GetFileInByteArrayFormatFromId(id);
  return File(byteArrayOfFile,"application/pdf");
}

Assuming GetFileInByteArrayFormatFromId returns the byte array version of the file after reading from your storage/azure. You may consider caching some of the files in your environment so that you do not need to reach out to azure to get it on every request.

If you can read the file as a file stream, the File method has an overload which takes that as well

public ActionResult View(int id)
{
  // id is a unique id for the file. Use that to get the file from your storage.
  FileStream fileStream = GetFileStreamFromId(id);;
  return File(fileStream, "application/pdf","Myfile.pdf");
}

And if you have the file available in your server(the cached files), You can use another overload of File method where you will pass the path instead of the byte array.

public ActionResult View(int id)
{
  var f = Server.MapPath("~/Content/Downloads/sampleFile.pdf");
  return File(f,"application/pdf");
}

If the browser has the support to display the content type of the response, the response will be displayed in the browser. Most of the major browsers supports rendering pdf files.

There is another overload of the File method which takes the download file name which the browsers' save/download dialog will use so that user can save it his local computer and/or open.

public ActionResult View(int id)
{
    var pathToTheFile=Server.MapPath("~/Content/Downloads/sampleFile.pdf");
    return File(pathToTheFile, MimeMapping.GetMimeMapping(pathToTheFile),"Myfile.pdf");
}
public ActionResult ViewFromByteArray(int id)
{
    byte[] byteArrayOfFile=GetFileInByteArrayFormatFromId(id);
    return File(byteArrayOfFile, "application/pdf","Myfile.pdf");
}

With this, user will get a download prompt from the browser.

like image 146
Shyju Avatar answered Sep 19 '22 12:09

Shyju