4

I have an ASP.NET MVC5 web app which generates (via database queries) some very large CSV files for export. Building up the entire file in memory can cause load issues, so rather than buffering the file on the server we stream the bytes as we generate them.

My question is: what are my options for error handling if a failure occurs in the middle of generating the data?. I know it's too late to set a 500 status code at this point (since the headers have already been sent), but is there something I can do to cause the browser to realize that the download was interrupted?

// my controller code
public async Task<ActionResult> StreamLotsOfData()
{
    // [set some headers for the file download]

    this.Response.BufferOutput = false; // allow streaming

    foreach (var row in GetStreamingDataSet())
    {
        await this.Response.Output.WriteLineAsync(GenerateCsvLine(row));
    }

    return new EmptyResult();
}

// my error handling code
public sealed class MyExceptionFilter : IExceptionFilter
{
    void IExceptionFilter.OnException(ExceptionContext filterContext)
    {
        if (filterContext.HttpContext.Response.HeadersWritten)
        {
            // [log the error]
            filterContext.ExceptionHandled = true;
            // [what can I do here?]
            return;
        }

        // [normal error handling code which generates an error response]
    }
}

EDIT: I found this post, but I'm not sure how to take advantage of any of the suggestions there in ASP.NET.

EDIT: I found one potential approach which is to download a zip archive of the CSV instead of directly downloading the CSV. With zip, it's easy enough to corrupt the zip file by injecting some extra bytes at the end in case of failure. That way the user has at least some indication that the download was not successful. Streaming a zip file is a little tricky due to this bug. That same connect issue describes a workaround, though.

Community
  • 1
  • 1
ChaseMedallion
  • 20,860
  • 17
  • 88
  • 152

0 Answers0