【问题标题】:How can I detect when a file download has completed in ASP.NET?如何在 ASP.NET 中检测文件下载何时完成?
【发布时间】:2011-01-13 02:14:29
【问题描述】:

我有一个弹出窗口,显示“正在下载您的文件,请稍候”。此弹出窗口还执行以下代码以开始文件下载。文件下载完成后如何关闭弹出窗口?我需要一些方法来检测文件下载是否已完成,以便我可以调用 self.close() 来关闭此弹出窗口。

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();

【问题讨论】:

  • 简短回答...你不能!
  • 下载是客户端,ASP.NET是服务器端。
  • 你不能。为什么要锁定用户界面等待下载。当然,您的页面的正确操作可以继续进行,而无需等待,因为不能依赖下载的文件。网络不是这样工作的,你为什么要这样做?

标签: c# javascript asp.net


【解决方案1】:

一个想法:

如果您在服务器端代码中通过逐块写入响应流来处理自己下载的文件,那么您将知道文件何时完成下载。您只需将 FileStream 连接到响应流,逐块发送数据,并在完成后重定向。这可以在您的弹出窗口中。

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

确保在写出响应流时检查 Response.IsClientConnected。

【讨论】:

    【解决方案2】:

    有一种解决方案,您可以通过将文件作为较小的数据包传输来跟踪下载状态,并检查是否所有数据包都已传输。 解决方案不是我的,但你可以在这里找到: 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】:

      一些技巧包括知道缓冲区的最后一块何时发送或检查HttpResponse.IsClientConnected 属性。

      【讨论】:

        【解决方案4】:

        这样做的方法是在您的弹出窗口中通过 AJAX 轮询调用服务器以获取一些表明文件已刷新的响应。

        例如:在发送文件之前,将 sessionID+FileName 存储在数据库或会话中,或者你有什么。

        在客户端,在您的弹出窗口中,通过 AJAX 轮询 Web 服务 - 这甚至可以是像 Bool IsContentFlushed(string sessionID, string fileName); 这样的 WebMethod

        在您执行Response.Flush(); 之后,从您的商店中删除此 sessionID+FileName。

        调用Response.Close() 而不是Response.End() - 后者非常残忍,而且通常是过度杀戮。

        【讨论】:

          【解决方案5】:

          尽管这是一个古老的问题,但它一直没有得到回答,我相信它应该得到一个(更好的)答案:

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

          【讨论】:

            【解决方案6】:

            我在 Javascript 中处理问题的方式不同,这可能适合您,也可能不适合您。

            • 创建一个隐藏的 DIV 元素,使用 消息“文件正在下载...” 而不是弹出框。
            • 下载时显示div 开始
            • 一旦在 单击表单,隐藏 div 再次..
            • 您还可以设置一个计时器来隐藏 so之后的下载消息div 时间...

            我认为一旦用户点击另一个元素,她要么已经知道下载完成,要么她准备做其他事情,所以消息变得无关紧要并且可以消失......

            【讨论】:

            • 此方法假定下载将花费指定的时间,并且当用户知道下载已完成时会执行某些操作。如果用户从不接触计算机并且文件需要很长时间才能下载,则该消息将在文件实际下载之前消失。它也没有回答问题,因为它忽略了模式。
            猜你喜欢
            • 2023-03-26
            • 2010-09-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-11
            • 1970-01-01
            • 2019-09-15
            • 1970-01-01
            相关资源
            最近更新 更多