Search code examples
htmlasp.net-web-apidownloaddownloading-website-files

Why does my file download link seem to work, but is unable to find the file?


I added this HTML to a page that I render via a REST call:

StringBuilder builder = new StringBuilder();
. . .
builder.Append("<p></p>");
builder.Append("<a href=\"/App_Data/MinimalSpreadsheetLight.xlsx\" download>");
builder.Append("<p></p>");
. . .
return builder.ToString();

My ASP.NET Web API project has a folder named "App_Data" which does contain a file named "MinimalSpreadsheetLight.xlsx"

The download link is indeed rendered on the page, and clicking it does appear, at first, to download the file (it has the Excel icon, and it bears the file name), but beneath that it says "Failed - No file":

enter image description here

Is the problem with my HTML, or the path I'm using, or file permissions, or what?

I've only tested this with Chrome, so far, BTW. IOW, it's not an IE issue.

UPDATE

I tried it with a leading squiggly, too:

builder.Append("<a href=\"~/App_Data/MinimalSpreadsheetLight.xlsx\" download=\"Spreadsheet file\">");

...yet, alas, to no avail.

UPDATE 2

I changed the pertinent line of HTML to this:

builder.Append("<a href=\"App_Data/MinimalSpreadsheetLight.xlsx\" download=\"Minimal Spreadsheet file\">");

...and it displays in the source like so (with some context):

<p>(Invoice Count excludes credits and re-delivery invoices)</p><p></p><p></p><a href="App_Data/MinimalSpreadsheetLight.xlsx" download="Minimal Spreadsheet file">

...but the link does not appear at all.

UPDATE 3

I was misled by this reference, which showed no text being added; I changed the code to this:

builder.Append("<a href=\"App_Data/MinimalSpreadsheetLight.xlsx\" download=\"Minimal Spreadsheet file\">Spreadsheet file</a>");

...(adding "Spreadsheet file" and closing out the anchor tag), and now the link appears; however, I still get the "Failed - No file" msg, and 2-clicking the "downloaded file" does nothing.

UPDATE 4

I tried two other permutations of what's seen in Update 3, namely with the forward whack reintroduced prior to "App_Data":

builder.Append("<a href=\"/App_Data/MinimalSpreadsheetLight.xlsx\" download=\"Minimal Spreadsheet file\">Spreadsheet file</a>");

...and with both the squiggly prepended and the forward whack:

builder.Append("<a href=\"~/App_Data/MinimalSpreadsheetLight.xlsx\" download=\"Minimal Spreadsheet file\">Spreadsheet file</a>");

...but the results are the same in any of these permutations ("Failed - no file").

UPDATE 5

I also tried it without the "App_Data" at all, on the off change that is not needed:

builder.Append("<a href=\"MinimalSpreadsheetLight.xlsx\" download=\"Minimal Spreadsheet download\">Spreadsheet file</a>");

...but the same "Failed - No file" is the result of that attempt, too.

UPDATE 6

Okay, so I tried this, too (single quotes):

builder.Append("<a href='/App_Data/MinimalSpreadsheetLight.xlsx' download='Minimal Spreadsheet file'>Spreadsheet file</a>");

...but no change. The file is there:

enter image description here

...so why is it not seen or accessible?

UPDATE 7

This:

string fullPath = HttpContext.Server.MapPath("~/App_Data/MinimalSpreadsheetLight.xlsx");

... (which I got from here) fails to compile with, "An object reference is required for the non-static field, method, or property 'System.Web.HttpContext.Server.get'

2-clicking the err msg highlights just "Server"

UPDATE 8

This (which I got from the same place as what I tried in Update 7):

string justDataDir = AppDomain.CurrentDomain.GetData("DataDirectory").ToString();
string url2 = string.Format("<a href='{0}/MinimalSpreadsheetLight.xlsx' download='Minimal Spreadsheet file'><button type=\"button\">Spreadsheet file</button></a>", justDataDir);
builder.Append(url2);

...does nothing; clicking the link doesn't even give me a fake/failed download now...

justDataDir is:

C:\Projects\ProActWebReports\ProActWebReports\App_Data

url2 is:

<a href='C:\Projects\ProActWebReports\ProActWebReports\App_Data/MinimalSpreadsheetLight.xlsx' download='Minimal Spreadsheet file'><button type="button">Spreadsheet file</button></a>

UPDATE 9

I noticed on further fine-tooth-combing that url2 had a forward whack in it; I changed it so that all the whacks were back, but it made no difference to Update 8's results: clicking the link does nothing whatsoever.

If somebody solves this, it will definitely get bountified after the fact.

UPDATE 10

Maybe what I really need to do is, instead of the simple html, add some jQuery that will download the file. But the question is, can jQuery access the App_Data folder any better than raw/simple html can?


Solution

  • The app_data folder is used by iis and asp.net as a private area in which to put database files which can only be accessed by code running on the server.

    If you try to access the folder directly via your browser you will get a permissions error.

    In order to make the files available for download, move them the a folder under 'Content' (if you have an mvc site) and ensure that your web.config allows the .xlsx exention to be downloaded.

    It may depend on what version of iis you are using.

    Downloading Docx from IE - Setting MIME Types in IIS