- PR -

ファイルのダウンロード完了を検知後、遷移させたい

投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-06 22:14
この辺はいくらでも方法はあるので、議論はいくらでも出来ると思いますが、
取り合えず私がやるとすればの話で。

最初にAjaxでコネクションを貼りに行きますが、
Ajax用のサーブレットはこんな感じのロジックになるのではと。
コード:
HttpSession session = request.getSession();
session.setAttribute("request", request);
synchronized(request){
    try{
       request.wait();
    }catch(InterruptedException e){
    }
}


で、JavaScriptの方はこんな感じでしょう。
コード:
var request = ...//XHR
var handler = function(){
    location.href="xxxx";
};
//リクエストの非同期送信と、完了ステートに対するハンドラの処理(省略)
//ダウンロード処理(省略)


で、ダウンロード側は、こんな感じ。
コード:
//レスポンスに書き込む処理(省略)
HttpSession session = request.getSession();
HttpServletRequest req = (HttpServletRequest) session.getAttribute("request");
session.removeAttribute("request");
synchronized(req){
   req.notifyAll();
}


非同期通信の場合、完了時のイベントを受け取って処理することができますが、
Ajax用のサーブレットでリクエストを待機させることで、
送り側のJavaScriptで完了イベントを発生させないようなイメージです。

ダウンロードが完了してから待機しているリクエストを解放することによって、
JavaScript側で完了イベントを発生させて画面遷移させています。
「Comet」というキーワードで検索すれば分かるかなと思います。

ありきたりな処理と細かいエラーチェックとかも省いています。
思いつきで書いたので構文とか名前に間違いがあるかもです。
ニュアンスは伝わると思うのですが。。。

ちなみに、クラスタ環境では絶対に動きませんのであしからず。
取り合えず「こういうトリッキーなやりかたもありますよ」って事だけ
分かっていただければなと思います。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2007-03-06 22:28
ん、この実装↑だと空きスレッドが枯渇していたり、Webサーバの最大コネクション数に達していた場合ダウンロード中に request.wait() に到達せず、デッドロックしませんか?
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-03-06 23:21
>インギさん

正直そこまで考慮してません。
実際に本気で実装しようとすると、もっと書くことが多くなると思います。
ロック条件とかダウンロード開始条件とか・・・

取り合えず「こんなに面倒な事なんですよ」って事が伝わればいいかなと。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-03-07 00:38
引用:

かつのりさんの書き込み (2007-03-06 22:14) より:
ちなみに、クラスタ環境では絶対に動きませんのであしからず。
取り合えず「こういうトリッキーなやりかたもありますよ」って事だけ
分かっていただければなと思います。



クラスタ環境でも多くの場合は動いてしまうから困りますね。
J2EEなAPサーバの場合はSticky Sessionの類を使うでしょうし。

で、サービス止めずに一台ずつクラスタから切り離してメンテ
するような運用をした時に発覚したりしそうな感じです
jazz
会議室デビュー日: 2007/03/05
投稿数: 4
投稿日時: 2007-03-07 22:05
お世話になっております。
レスありがとうございます。

インギさん>
引用:

アップロード中のプログレスバーであれば、 YouSendItとかでやっていますね。


早速アクセスし、試してみました。
これも状況が似ていますね。
後ほどソースの方を細かく見ていきたいと思います。
引用:

・「ダウンロード中です」画面に遷移
・setTimeout() で定期的に送信状況をポーリング
・完了したら画面遷移
といった雰囲気でしょうか。
まず試してみてください。



ありがとうございます。
似たようなことをやってるサイトを見るというのも大事ですね。
教えてくださってどうもありがとうございます!

かつのりさん>
引用:

この辺はいくらでも方法はあるので、議論はいくらでも出来ると思いますが、
取り合えず私がやるとすればの話で。

最初にAjaxでコネクションを貼りに行きますが、
Ajax用のサーブレットはこんな感じのロジックになるのではと。
コード:

HttpSession session = request.getSession();
session.setAttribute("request", request);
synchronized(request){
try{
request.wait();
}catch(InterruptedException e){
}
}


で、JavaScriptの方はこんな感じでしょう。
コード:

var request = ...//XHR
var handler = function(){
location.href="xxxx";
};
//リクエストの非同期送信と、完了ステートに対するハンドラの処理(省略)
//ダウンロード処理(省略)


で、ダウンロード側は、こんな感じ。
コード:

//レスポンスに書き込む処理(省略)
HttpSession session = request.getSession();
HttpServletRequest req = (HttpServletRequest) session.getAttribute("request");
session.removeAttribute("request");
synchronized(req){
req.notifyAll();
}


具体的なプログラムまで書いてくださってとても助かります!
この場合はJavaScriptにダウンロードの処理を書くのですか?
うーん、JavaScriptの事をもうちょい勉強しなきゃならなそうですね・・・
引用:

非同期通信の場合、完了時のイベントを受け取って処理することができますが、
Ajax用のサーブレットでリクエストを待機させることで、
送り側のJavaScriptで完了イベントを発生させないようなイメージです。

ダウンロードが完了してから待機しているリクエストを解放することによって、
JavaScript側で完了イベントを発生させて画面遷移させています。
「Comet」というキーワードで検索すれば分かるかなと思います。


Cometについて検索しました。
HTTP通信を繋ぎっぱなしにしてリアルタイム性を向上させる等
Ajaxの派生(?)というかポーリングの種類の様な感じかなぁと理解しました。
引用:

ありきたりな処理と細かいエラーチェックとかも省いています。
思いつきで書いたので構文とか名前に間違いがあるかもです。
ニュアンスは伝わると思うのですが。。。

ちなみに、クラスタ環境では絶対に動きませんのであしからず。
取り合えず「こういうトリッキーなやりかたもありますよ」って事だけ
分かっていただければなと思います。


う〜ん、、、トリッキーな方法を取るべきなのか。
しかしトリッキーな方法を取らずには今の機能は実現できず・・・といったところでしょうか。
うーん・・・

スキルアップ/キャリアアップ(JOB@IT)