Download a Large file Async in ASP.NET C#

3.5k views Asked by At

I have the code below which works well for small files but for large files it generates the zip as required but doesn't download it. I get all sorts of errors including Timeout (which I have managed to resolve). The other problem is that it runs in Sync. The largest file I have generated myself is a 330MB zip file with about 30 HD images attached to it. But this can even go to GBs as the user can choose to download about 100 or even more HD images at once.

To resolve both issues, I thought downloading in async may help in both cases. I want to alert the user that their download has started, and that they will be notified when it is ready.

I am thinking of sending the stream down if the client IsConnected (then delete the file) or sending an email to ask them to download the file if they have decided to logout (then delete the file using the offline download link). I just don't know where or how to write async code, or if what I want to do can actually be done if the user decides to logout.

Here's my current code:

private void DownloadFile(string filePath)
{
    FileInfo myfile = new FileInfo(filePath);

    // Checking if file exists
    if (myfile.Exists)
    {
        // Clear the content of the response
        Response.ClearContent();

        // Add the file name and attachment, which will force the open/cancel/save dialog box to show, to the header
        Response.AddHeader("Content-Disposition", "attachment; filename=" + myfile.Name);

        // Add the file size into the response header
        Response.AddHeader("Content-Length", myfile.Length.ToString());

        // Set the ContentType
        Response.ContentType = "application/octet-stream";

        Response.TransmitFile(filePath);
        Response.Flush();

        try
        {
            myfile.Delete();
        }
        catch { }
    }
}
1

There are 1 answers

1
Gridly On

I don't know about Async downloads from asp.net applications so I can't address that question. But I have run into enough download issues to always start from the same place.

First, download from a generic handle (ASHX) and not a web form. The webform wants to do extra processing at the end of the request that can cause problems. You question didn't state if you are using a web form or generic handler.

Second, always end the request with the ApplicationInstance.CompleteRequest() method call. Don't use Request.Close() or Request.End()

Those two changes have often cleaned up download issues for me. Try these change and see if you get the same results. Even if you do get the same results this is a better way of coding downloads.

Finally, as an aside, only catch appropriate exceptions in the try-catch bock.

Your code would be like this:

public class Handler1 : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        // set from QueryString
        string filePath = "...";

        FileInfo myfile = new FileInfo(filePath);

        // Checking if file exists
        if (myfile.Exists)
        {
            // Clear the content of the response
            context.Response.ClearContent();

            // Add the file name and attachment, which will force the open/cancel/save dialog box to show, to the header
            context.Response.AddHeader("Content-Disposition", "attachment; filename=" + myfile.Name);

            // Add the file size into the response header
            context.Response.AddHeader("Content-Length", myfile.Length.ToString());

            // Set the ContentType
            context.Response.ContentType = "application/octet-stream";

            context.Response.TransmitFile(filePath);
            context.Response.Flush();

            HttpContext.Current.ApplicationInstance.CompleteRequest();

            try
            {
                myfile.Delete();
            }
            catch (IOException)
            { }
        }
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}