One possible solution uses JavaScript on the client.(一种可能的解决方案是在客户端上使用JavaScript。)
The client algorithm:(客户端算法:)
- Generate a random unique token.(生成随机的唯一令牌。)
- Submit the download request, and include the token in a GET/POST field.(提交下载请求,并将令牌包含在GET / POST字段中。)
- Show the "waiting" indicator.(显示“正在等待”指示器。)
- Start a timer, and every second or so, look for a cookie named "fileDownloadToken" (or whatever you decide).(启动一个计时器,然后每隔一秒钟左右,查找一个名为“ fileDownloadToken”(或您决定的内容)的cookie。)
- If the cookie exists, and its value matches the token, hide the "waiting" indicator.(如果cookie存在,并且其值与令牌匹配,则隐藏“等待”指示符。)
The server algorithm:(服务器算法:)
- Look for the GET/POST field in the request.(在请求中查找GET / POST字段。)
- If it has a non-empty value, drop a cookie (eg "fileDownloadToken"), and set its value to the token's value.(如果它具有非空值,则删除一个cookie(例如“ fileDownloadToken”),并将其值设置为令牌的值。)
Client source code (JavaScript):(客户端源代码(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;
}
Example server code (PHP):(服务器代码示例(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();
Where:(哪里:)
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
);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…