[解決済み] ブラウザがファイルのダウンロードを受信したことを検出する
質問
動的に生成されたファイルをユーザーがダウンロードできるページがあります。生成に時間がかかるので、"waiting"のインジケータを表示したいのですが、どうすればよいでしょうか?問題は、ブラウザがファイルを受信したことを検知して、インジケータを非表示にする方法がわからないことです。
非表示のフォームを要求しているのですが、これは POST をサーバーに送信し、その結果を隠しiframeをターゲットにします。これは、ブラウザーのウィンドウ全体を結果で置き換えないようにするためです。ダウンロードが完了したときに、iframeの"load"イベントが発生することを期待して、イベントを待機しています。
を返します。
Content-Disposition: attachment
ヘッダをファイルと共に表示し、ブラウザに "保存"ダイアログを表示させます。しかし、ブラウザはiframeで"load"イベントを発生させません。
私が試した方法の1つは
multi-part
のレスポンスがあります。つまり、空の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ファイルを受信して "load" イベントが発生し "Save" ダイアログが表示されます。しかし インターネットエクスプローラ と サファリ Internet Explorer は "load"イベントを発生させますが、ファイルはダウンロードされません。 Safariがダウンロードする は発生せず、(間違った名前とコンテントタイプの)ファイルが表示されます。 "ロード" イベントが発生します。
別のアプローチとして、ファイル作成を開始するために呼び出し、準備が整うまでサーバーをポーリングし、その後、既に作成されたファイルをダウンロードすることも可能かもしれません。しかし、私はむしろサーバーに一時ファイルを作成するのを避けたいのです。
どうすればいいのでしょうか?
解決するには?
一 可能な解決策 は、クライアント側でJavaScriptを使用します。
クライアントのアルゴリズムです。
- ランダムなユニークトークンを生成します。
- ダウンロード要求を送信し、GET/POSTフィールドにトークンを含めます。
- waiting"インジケータを表示します。
- タイマーを起動し、約1秒ごとに "fileDownloadToken" という名前のクッキーを探します(またはあなたが決めたもの)。
- クッキーが存在し、その値がトークンに一致する場合、"waiting"インジケータを非表示にします。
サーバーのアルゴリズムです。
- リクエストの中からGET/POSTフィールドを探します。
- 空でない値を持つ場合、クッキー(例:"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ファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] 画面サイズ、現在のウェブページ、ブラウザウィンドウのサイズを取得する
-
[解決済み] Node.jsを使うタイミングをどう判断するか?
-
[解決済み] モバイル端末の検出にはどのような方法がありますか?
-
[解決済み] HTTPでファイルをダウンロードするには?
-
[解決済み] Safari、Chrome、IE、Firefox、Operaのブラウザを検出する方法は?
-
[解決済み] ファイルのダウンロードにContent-Type: application/octet-streamは必要ですか?
-
[解決済み] ajaxポストからのファイルダウンロードを処理する
-
[解決済み] ページから移動することなく、ダウンロードウィンドウを開く最も簡単な方法
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Javascript:getElementById対getElementsById(両方が別のページで動作する)。
-
[解決済み】フォームコントロールの値アクセサがない
-
[解決済み】jquery $.ajaxオブジェクトのresponseJSONプロパティを取得する方法 [重複]。
-
[解決済み】JavaScript "Uncaught TypeError: object is not a function" 連想性の質問
-
[解決済み】別のjsファイル内でJavaScriptの関数を呼び出す
-
[解決済み】JavaScriptのボタンonclickが機能しない
-
[解決済み】SyntaxError: ChromeのJavascriptコンソールでUnexpected Identifierが発生する。
-
[解決済み】Redux TypeError: 未定義のプロパティ 'apply' を読み取れない
-
[解決済み】TypeError: AngularJSで未定義のプロパティ'get'を読み取れない
-
[解決済み】未定義のプロパティ 'forEach' を読み取ることができない