当前位置: 首页 > 面试题库 >

JavaScript检测浏览器何时接收文件下载

拓拔元徽
2023-03-14
问题内容

我有一个页面,允许用户下载动态生成的文件。生成需要很长时间,因此我想显示一个“等待”指示器。问题是,我不知道如何检测浏览器何时收到文件,因此可以隐藏指示器。

我正在以隐藏的形式发出请求,该请求会发布到服务器,并以隐藏的iframe作为结果。这样一来,我就不会用结果替换整个浏览器窗口。我在iframe上侦听“加载”事件,希望下载完成后将触发该事件。

我随文件返回一个“ Content-Disposition:附件”标头,这将导致浏览器显示“保存”对话框。但是浏览器不会在iframe中触发“加载”事件。

我尝试的一种方法是使用多部分响应。因此它将发送一个空的HTML文件以及附加的可下载文件。例如:

Content-type: multipart/x-mixed-replace;boundary="abcde"

--abcde
Content-type: text/html

--abcde
Content-type: application/vnd.fdf
Content-Disposition: attachment; filename=foo.fdf

file-content
--abcde

这在Firefox中有效;它会收到一个空的HTML文件,触发“加载”事件,然后显示可下载文件的“保存”对话框。但是它在IE和Safari上失败;IE会触发“加载”事件,但不会下载文件,而Safari会下载文件(具有错误的名称和内容类型),并且不会触发“加载”事件。

一种不同的方法可能是调用开始文件创建,然后轮询服务器直到服务器就绪,然后下载已创建的文件。但是我宁愿避免在服务器上创建临时文件。

有谁有更好的主意吗?


问题答案:

一种可能的解决方案是在客户端上使用JavaScript。

客户端算法:

  1. 生成随机的唯一令牌。
  2. 提交下载请求,并将令牌包括在GET / POST字段中。
  3. 显示“正在等待”指示器。
  4. 启动一个计时器,然后每隔一秒钟左右,查找一个名为“ fileDownloadToken”(或您决定的内容)的cookie。
  5. 如果cookie存在,并且其值与令牌匹配,则隐藏“等待”指示符。

服务器算法:

  1. 在请求中查找GET / POST字段。
  2. 如果它具有非空值,则删除一个cookie(例如“ fileDownloadToken”),并将其值设置为令牌的值。

客户端源代码(JavaScript):

function getCookie( name ) {
  var parts = document.cookie.split(name + "=");
  if (parts.length == 2) return parts.pop().split(";").shift();
}

function expireCookie( cName ) {
    document.cookie = 
        encodeURIComponent(cName) + "=deleted; expires=" + new Date( 0 ).toUTCString();
}

function setCursor( docStyle, buttonStyle ) {
    document.getElementById( "doc" ).style.cursor = docStyle;
    document.getElementById( "button-id" ).style.cursor = buttonStyle;
}

function setFormToken() {
    var downloadToken = new Date().getTime();
    document.getElementById( "downloadToken" ).value = downloadToken;
    return downloadToken;
}

var downloadTimer;
var attempts = 30;

// Prevents double-submits by waiting for a cookie from the server.
function blockResubmit() {
    var downloadToken = setFormToken();
    setCursor( "wait", "wait" );

    downloadTimer = window.setInterval( function() {
        var token = getCookie( "downloadToken" );

        if( (token == downloadToken) || (attempts == 0) ) {
            unblockSubmit();
        }

        attempts--;
    }, 1000 );
}

function unblockSubmit() {
  setCursor( "auto", "pointer" );
  window.clearInterval( downloadTimer );
  expireCookie( "downloadToken" );
  attempts = 30;
}

服务器代码示例(PHP):

$TOKEN = "downloadToken";

// Sets a cookie so that when the download begins the browser can
// unblock the submit button (thus helping to prevent multiple clicks).
// The false parameter allows the cookie to be exposed to JavaScript.
$this->setCookieToken( $TOKEN, $_GET[ $TOKEN ], false );

$result = $this->sendFile();

哪里:

public function setCookieToken(
    $cookieName, $cookieValue, $httpOnly = true, $secure = false ) {

    // See: http://stackoverflow.com/a/1459794/59087
    // See: http://shiflett.org/blog/2006/mar/server-name-versus-http-host
    // See: http://stackoverflow.com/a/3290474/59087
    setcookie(
        $cookieName,
        $cookieValue,
        2147483647,            // expires January 1, 2038
        "/",                   // your path
        $_SERVER["HTTP_HOST"], // your domain
        $secure,               // Use true over HTTPS
        $httpOnly              // Set true for $AUTH_COOKIE_NAME
    );
}


 类似资料:
  • 问题内容: 您如何确定用户是否按下浏览器中的“后退”按钮? 您如何使用系统在单页Web应用程序内强制使用页内后退按钮? 到底为什么浏览器后退按钮不触发自己的事件!? 问题答案: (注意:根据Sharky的反馈,我提供了用于检测退格的代码) 因此,我经常在SO上看到这些问题,并且最近遇到了我自己控制后退按钮功能的问题。在为我的应用程序寻找最佳解决方案(带哈希导航的单页)几天后,我提出了一个简单的,跨

  • 问题内容: 如何使用JavaScript确定确切的浏览器和版本? 问题答案: 顾名思义,这将告诉您浏览器提供的名称和版本号。 当您在多个浏览器上测试新代码时,它对于对测试结果和错误结果进行排序非常方便。

  • 问题内容: 我正在寻找一个函数,如果用户具有移动浏览器,该函数将返回布尔值。 我知道我可以通过使用正则表达式来使用和编写该函数,但是对于不同的平台,用户代理种类繁多。我怀疑匹配所有可能的设备会很容易,并且我认为这个问题已经解决了很多次,因此应该为此类任务提供某种完整的解决方案。 我当时在看这个站点,但是可悲的是脚本太神秘了,以至于我不知道如何使用它来创建一个返回true / false的函数。 问

  • 问题内容: 如何找到浏览器的Javascript引擎版本以及对ECMAScript 6的支持? 我只是想知道浏览器的版本,而不是引擎的版本。 问题答案: 特征检测 我建议您使用 功能检测, 而不要使用启发式方法检测浏览器的引擎。为此,您可以简单地 在语句中包装一些代码,或使用一些语句。 例如: 为什么功能检测比浏览器/引擎检测更好? 在大多数情况下,有多种原因可以使特征检测成为最佳选择: 您不必依

  • 问题内容: 我一直在寻找可以让我检测访问该网站的用户是否使用Firefox3或4的代码。我发现的所有代码都是用于检测浏览器类型而不是版本的代码。 如何检测这样的浏览器版本? 问题答案: 您可以看到浏览器说的内容,并将该信息用于记录或测试多个浏览器。

  • 问题内容: 如何使用JavaScript检测Safari浏览器?我在下面尝试过代码,它不仅可以检测Safari,还可以检测Chrome浏览器。 问题答案: 您可以轻松地使用Chrome的索引来过滤掉Chrome: