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

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

我正在以隐藏的形式发出请求,该请求会发布到服务器,并以隐藏的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

);

}

以上是 JavaScript检测浏览器何时接收文件下载 的全部内容, 来源链接: utcz.com/qa/419718.html

回到顶部