- PR -

ファイル保存キャンセルをキャッチ

投稿者投稿内容
あすか
ぬし
会議室デビュー日: 2006/07/12
投稿数: 309
投稿日時: 2006-12-14 18:03
お世話になります。

ファイルダウンロードサーブレット(フレームワーク無し)を作成し
サーバのファイルをダウンロードさせることをやっています。
参考までに。
コード:
    String fileName = request.getParameter("name");

    try {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(file);
        } catch (FileNotFoundException e1) {
            throw new TargetFileNotFoundException(e1);
        }
        response.setContentType("application/octet-stream");
        String fileName;
        try {
            fileName = new String(file.getName().getBytes("SJIS"), "ISO8859_1");
        } catch (UnsupportedEncodingException e3) {
            fileName = "EncodingMiss" + file.getName();
        }
        response.setHeader(
                "Content-Disposition",
                "attachment; filename=" + fileName);
        // ファイルをバイトで読んで送信
        int size;
        byte[] buffer = new byte[1024];
        try {
            while ((size = inputStream.read(buffer)) != -1) {
                response.getOutputStream().write(buffer, 0, size);
                response.getOutputStream().flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (Exception e2) {
                    e.printStackTrace();
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }



ファイルのダウンロードは無事行うことが出来ます。
ここで欲を出しました。

ファイルの保存ダイアログにて
ユーザが「キャンセル」したことを知ることができないだろうか。

過去の投稿を参照するとIQExceoptionが発生したりしていますが
残念ながら発生を確認できませんでした。
(ファイルサイズが5,844byteと小さいから?)

「キャンセル」イベントを拾うことは出来ないものなのでしょうか。
JavaScript等、クライアントスクリプトでも構いません。

何かご存知でしたらよろしくお願いします。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-12-14 18:25
>(ファイルサイズが5,844byteと小さいから?)
大きなファイルで試してみれば切り分けられますね。

クライアント側での検出は JavaScript では簡単にはできないんじゃないかと思います。

キャンセル・完了を定期的にサーバサイドに XMLHttpRequest で問いあわせるような仕組みを作って、送信ボタンを押したタイミングで setTimeout を使って呼び出すとかすればできるかも?

[ メッセージ編集済み 編集者: インギ 編集日時 2006-12-14 18:31 ]
sawat
大ベテラン
会議室デビュー日: 2006/08/02
投稿数: 112
投稿日時: 2006-12-14 18:48
引用:

インギさんの書き込み (2006-12-14 18:25) より:
クライアント側での検出は JavaScript では簡単にはできないんじゃないかと思います。

キャンセル・完了を定期的にサーバサイドに XMLHttpRequest で問いあわせるような仕組みを作って、送信ボタンを押したタイミングで setTimeout を使って呼び出すとかすればできるかも?


簡単にというか、原理的に不可能では?
ファイルのダウンロードを行っているリクエストの状況を他の画面のJavaScriptでチェックすることはできないですし、ダウンロードのレスポンスにスクリプトを入れても意味ないですし(一緒に保存されるだけ)…。

どうしても必要な場合は、ActiveXとかAppletを使ってダウンロードさせたりしなければならないと思います。その場合、セキュリティ周りでいろいろ面倒があると思いますが…。


#追記
レスポンスを無駄に長くしてあげれば、確かにIOExceptionはキャッチできるでしょうが、これも解決策としてはかなりいまいちですよね。信頼性も乏しそうですし。

[ メッセージ編集済み 編集者: sawat 編集日時 2006-12-14 18:52 ]
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-12-14 18:56
すいません、さっきの投稿、アップロードとダウンロードを取り違えていました。
JavaScript はレスポンスに含めるのではなくダウンロードする画面に織り込んでおくことを意図しておりました。
YouSendItのアップロードの進捗バーと同じ仕組みです。

短いファイルをダウンロードするとき、サーバサイドで IOException を検出できない様なケースではムリですね。

[ メッセージ編集済み 編集者: インギ 編集日時 2006-12-14 18:57 ]
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2006-12-14 19:14
引用:

インギさんの書き込み (2006-12-14 18:56) より:
短いファイルをダウンロードするとき、サーバサイドで IOException を検出できない様なケースではムリですね。



HTTPのヘッダ部を送った後、ボディ部の送信にまったをかけておいたら
どうなるでしょうかね?

妄想で書いていますが、たとえばIEの場合ですと、
ブラウザがダウンロード対象ファイルをどこに保存するかを
ユーザに選択させるためにダイアログを開いている段階で、
HTTPヘッダに設定したファイル名などが反映されていますから
hTTPヘッダまでは読み込みをしている筈ですよね。
そして、実際のダウンロードは保存ボタンを押下してから始まりますよね。

ストリーム的にはHTTPのヘッダ部が読み込めるところまで読み込んでから
ユーザのアクションを待って、読み込み再開となるはずです。
実際にはバッファリングされているのでしょうが、
明示的にボディ部の送信前でflush()してやって、
その後ボディ部を1バイト送信して読み込まれるのを待機…
としてやればIOExceptionの検出精度を高めることができるかもしれません。

あとはバッファサイズを小さくしてflush()しまくってやれば
ダウンロード途中でのキャンセルもそれなりに検出できるかも。
通信速度は低下するでしょうし、100%の検出は保障できないでしょうけども。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-12-14 19:36
>HTTPのヘッダ部を送った後、ボディ部の送信にまったをかけておいたら
お、なんだかイケそうですね! もちろんブラウザの実装に依存しますが。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2006-12-14 19:42
>nagiseさん
IEって、保存ダイアログが出ているときにも、
既にダウンロードしていませんか?これも妄想なんですが・・・

でかいファイルを落とすときに保存ダイアログを開きっぱなしにすると、
急激な速度で途中までダウンロードされるので、
クライアントのどこかでバッファリングしてるのかなと思いました。

ヘッダだけ送信して待つというのは面白そうですね。
今度機会があれば試してみます。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-12-14 19:56
引用:

かつのりさんの書き込み (2006-12-14 19:42) より:
>nagiseさん
IEって、保存ダイアログが出ているときにも、
既にダウンロードしていませんか?これも妄想なんですが・・・

でかいファイルを落とすときに保存ダイアログを開きっぱなしにすると、
急激な速度で途中までダウンロードされるので、
クライアントのどこかでバッファリングしてるのかなと思いました。


内部動作がどうなっているかなんてもちろん知らないのですが、
挙動を見てると、保存ダイアログ表示する前にダウンロードは開始
していますね。
なのでユーザがファイルを選ぶかキャンセルする前に、ダウンロードが
完了してしまうこともあります(と思います)。
こうなるとちょっと難しいかな。

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