How can I detect when a file download has complete

2020-05-18 04:12发布

问题:

I have a popup window that displays "Please wait while your file is being downloaded". This popup also executes the code below to start the file download. How can I close the popup window once the file download has completed? I need some way to detect that the file download has completed so I can call self.close() to close this popup.

System.Web.HttpContext.Current.Response.ClearContent();
System.Web.HttpContext.Current.Response.Clear();
System.Web.HttpContext.Current.Response.ClearHeaders();
System.Web.HttpContext.Current.Response.ContentType = fileObject.ContentType;
System.Web.HttpContext.Current.Response.AppendHeader("Content-Disposition", string.Concat("attachment; filename=", fileObject.FileName));
System.Web.HttpContext.Current.Response.WriteFile(fileObject.FilePath);
Response.Flush();
Response.End();

回答1:

An idea:

If you handle the file downloading yourself in server side code by writing chunk by chunk to the response stream, then you'll know when the file had finished downloading. You would simply have to connect the FileStream to the response stream, send data chunk by chunk, and redirecting after complete. This can be inside your popup window.

Response.ContentType = "application/octet-stream";
Response.AppendHeader("content-disposition", "attachment; filename=bob.mp3");
Response.AppendHeader("content-length", "123456789");

Make sure you check Response.IsClientConnected when writing out to the response stream.



回答2:

There is a solution where you can track the download status by transferring the file as smaller packets and check whether all the packets have been transferred. The solution is not mine but you can find it here: File Download in ASP.NET and Tracking the Status of Success/Failure of Download

//Function for File Download in ASP.Net in C# and 
//Tracking the status of success/failure of Download.
private bool DownloadableProduct_Tracking()
{
//File Path and File Name
string filePath = Server.MapPath("~/ApplicationData/DownloadableProducts");
string _DownloadableProductFileName = "DownloadableProduct_FileName.pdf";

System.IO.FileInfo FileName = new System.IO.FileInfo(filePath + "\\" + _DownloadableProductFileName);
FileStream myFile = new FileStream(filePath + "\\" + _DownloadableProductFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);

//Reads file as binary values
BinaryReader _BinaryReader = new BinaryReader(myFile);

//Ckeck whether user is eligible to download the file
if (IsEligibleUser())
{
//Check whether file exists in specified location
if (FileName.Exists)
{
    try
    {
    long startBytes = 0;
    string lastUpdateTiemStamp = File.GetLastWriteTimeUtc(filePath).ToString("r");
    string _EncodedData = HttpUtility.UrlEncode(_DownloadableProductFileName, Encoding.UTF8) + lastUpdateTiemStamp;

    Response.Clear();
    Response.Buffer = false;
    Response.AddHeader("Accept-Ranges", "bytes");
    Response.AppendHeader("ETag", "\"" + _EncodedData + "\"");
    Response.AppendHeader("Last-Modified", lastUpdateTiemStamp);
    Response.ContentType = "application/octet-stream";
    Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName.Name);
    Response.AddHeader("Content-Length", (FileName.Length - startBytes).ToString());
    Response.AddHeader("Connection", "Keep-Alive");
    Response.ContentEncoding = Encoding.UTF8;

    //Send data
    _BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin);

    //Dividing the data in 1024 bytes package
    int maxCount = (int)Math.Ceiling((FileName.Length - startBytes + 0.0) / 1024);

    //Download in block of 1024 bytes
    int i;
    for (i = 0; i < maxCount && Response.IsClientConnected; i++)
    {
        Response.BinaryWrite(_BinaryReader.ReadBytes(1024));
        Response.Flush();
    }
    //if blocks transfered not equals total number of blocks
    if (i < maxCount)
        return false;
    return true;
    }
    catch
    {
    return false;
    }
    finally
    {
    Response.End();
    _BinaryReader.Close();
    myFile.Close();
    }
}
else System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(),
    "FileNotFoundWarning","alert('File is not available now!')", true);
}
else
{
System.Web.UI.ScriptManager.RegisterStartupScript(this, GetType(), 
    "NotEligibleWarning", "alert('Sorry! File is not available for you')", true);
}
return false;
}


回答3:

Some hacks are around that involves knowing when the last piece of the buffer has been sent or checking the HttpResponse.IsClientConnected property.



回答4:

I handle the problem differently in Javascript, which might or might not work for you.

  • Create a hidden DIV element, with the message 'File is downloading...' rather than a pop-up box.
  • Show the div when the download starts
  • Once any other element on the forms is clicked, hide the div again..
  • You could also set a timer to hide the download message div after so amount of time...

I figure once the user clicks on another element, she either already knows the download is done, or she is ready to do something else, so the message becomes irrelevant and can go away....



回答5:

The way to do that is in your pop-up to call the server via AJAX polling for some response which would indicate the file was flushed.

Ex: right before sending the file, store sessionID+FileName in a DB or session or what have you.

On the client, in your popup, poll a web-service via AJAX - this could even be a WebMethod like Bool IsContentFlushed(string sessionID, string fileName);

After you do Response.Flush(); remove this sessionID+FileName from your store.

Call Response.Close() instead of Response.End() - the later is very brutal, and is usually over-kill.



回答6:

Even though this is an old question it hasn't been answered all this time and I believe it deserves a (better) answer:

https://stackoverflow.com/a/59010319/313935