.NET Core & Download File: Use PhysicalFileResult, Not FileContentResult

While writing my Journal App to show how to use my Sqlstone framework, I wanted to allow the end user to download her Sqlite database.

I wrote up a very simple Controller method which looked like the following:

[HttpPost]
public ActionResult DownloadSqliteDb([FromQuery] String uuid)
{
var userDir = Path.Combine(webRootPath,uuid);
var journalDb = Path.Combine(userDir,templateDbFile);
Console.WriteLine(journalDb);
return new FileContentResult (System.IO.File.ReadAllBytes(journalDb), "application/x-sqlite3");
}

Worked On LocalHost

That last line returns the file to the client and saves it in their download directory.  I used some client code (JavaScript) to set the filename that is used to save the file on the client.

In case you’re interested, here’s all of the code that allows that to work.  This is just a snapshot but you can get the source by going to my Sqlstone Github repo and looking in the main.js file (in the wwwroot directory).

This code worked great when I tested it on localhost.

However, it failed when I ran it from my public web host.

Failure Gave Cryptic Error

When the error occurred, I got either a 500 (Internal Server Error) or a 404 (Not Found).

I double-checked that the path to the file was correct and it was.

The error was :
Request Error: ‘Referrer Policy: strict-origin-when-cross-origin’

That wasn’t terribly helpful and was difficult to find any information about when I searched.

I finally found this link which was a slightly different problem posted to a microsoft forum.

Somewhere in reading on that link I saw the following:

Please refer to the following SO article and try using PhysicalFileProvider.

There was a link associated so I took at look at the StackOverflow link.

That link mentioned that you should use PhysicalFileResult instead of the FileContentResult.

The Fix

I changed the one line of code in my Controller from:

return new FileContentResult (System.IO.File.ReadAllBytes(journalDb), "application/x-sqlite3");

to:

return new PhysicalFileResult(journalDb, "application/x-sqlite3");

Instantly, everything worked.  Previously the result would be a file filled with Error HTML.

Now the result file that was downloaded was the target Sqlite database that I was expecting.

You stumble upon some weird errors our here in Web Dev-Land and they aren’t often very clear.

Have you seen this problem?

Leave a Reply

Your email address will not be published. Required fields are marked *