Stephen Byrne
Stephen Byrne

Reputation: 7495

File download via Webapi controller - handling errors

I am working on an application that provides some links for users to download files. The page itself is served up by an MVC controller but the links are pointing to a WebAPI controller running on a separate domain.

(I would have preferred same domain but for various reasons it has to be a separate project and it will run on a separate domain. I don't think CORS is part of the issue anyway as this is not using XHR, but I mention it just in case).

So in development, the main MVC project is http://localhost:56626/Reports/

And the links on the page might look like this:

<a href="http://localhost:51288/ReportDownload?ID=12345">Report 12345</a>

where port 51288 is hosting the Web API.

The WebAPI controller uses ReportID to locate a file, and write its contents into the response stream, setting the disposition as an attachment:

//security.permission  checks and scaffolding/database interaction
//left out for clarity
 try
 {
    string filename = @"C:\ReportFiles\TestReport.csv";
    var stream = new FileStream(path, FileMode.Open);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = new MediaTypeHeaderValue("text/csv");
    var disp = new ContentDispositionHeaderValue("attachment");
    disp.FileName = "TestReport.csv";
    result.Content.Headers.ContentDisposition = disp;
    return result;
}
catch(Exception ex)
{
   //how to return a response that won't redirect on error?
}

By doing this the user can then click on the link and without any redirection, the user gets prompted to save or open the file, which is what I want; they stay on the original page with the links and just get an Open/Save dialog from the browser.

The problem arises when something goes wrong in the Web API controller - either an exception or some internal logic condition that means the file cannot be downloaded.

Now to be honest, I don't even understand how the browser can do the "in place" File/Save dialog in the first place:

I suppose I could just catch any exception in the controller and send back a dummy file called "Error.csv" with contents "Ha Ha Nope!" or something similar, but that would be a last resort...any ideas welcome!

Upvotes: 2

Views: 2851

Answers (1)

Lars H&#246;ppner
Lars H&#246;ppner

Reputation: 18402

If the user clicks on the link, the browser will follow it - then depending on the response headers and browser configuration, it'll either show the file dialog or render directly - you can't really change that behavior (apart from using preventDefault when the link is clicked, which kind of defeats the purpose).

I'd suggest taking a closer look at http://jqueryfiledownload.apphb.com/ which lets you do something like this:

$.fileDownload('some/file/url')
    .done(function () { alert('File download a success!'); })
    .fail(function () { alert('File download failed!'); });

Then you could bind the download action using jQuery.

Upvotes: 4

Related Questions