質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

ファイルの複数ダウンロードについて

解決済

回答 4

投稿

  • 評価
  • クリップ 3
  • VIEW 19K+

kurage

score 16

こんにちは。

web画面でファイルを複数選択し、選択されたファイルをダウンロードする際の実装方法について、お力添えいただきたいと思います。

<使用ツール>
Windows7、IE9、Javascript、Java1.6、struts

<要件>
1.選択したファイルはzipにしない
2.選択できるファイル数に制限はない
3.ファイルサイズは個々で異なる
4.ファイル数分のwindowは開きたくない
5.ファイルの保存はユーザーが行う(ファイル名の変更など)

Javascriptを用いてファイル数分のwindowを開いてダウンロードを行うことはできたのですが、要件4.に該当してしまうので、1画面内で実装したいと考えています。

<% String fileName = (String)request.getParameter("FILE"); %>

<html>
<scrpit>
  function windowReload() {
    // リクエストにファイル名を設定するメソッドの実行
    document.forms[0].method="setFile";
    document.forms[0].submit():
  }
</script>
<body onload="windowReload()">
<iframe src='<%= "download.do?FILE=" + fileName %>'>
</iframe>
</body>
</html>

上記のように、一つ目のファイルをwindow.open()実行時にリクエストに指定し、以降はsetFile()を呼び出すようにし、ダウンロード自体はiframeでの「download.do」で実行しようとしたのですが、wineowReload()が呼び出されるたびにダウンロード処理が中断してしまい、処理を行うことができませんでした。

上記処理について、ご教授の程宜しくお願い致します。
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

こんちには。

Ajaxでファイルダウンロード用のServletをファイル数分呼び出し、
ファイルダウンロード用のServlet側では、responseにファイルのStreamを直接セットし、
fowardはさせないようにすればできると思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/10 21:17 編集

    こんばんわ。
    もうちょっとな感じですね。
    > また、ファイルダウンロード用のサーブレットでは、受け取ったresponseからOutputStreamを取得し、ファイルの内容を設定してwrite()を実行しました。
    ファイルダウンロード用のサーブレットはforwardしないように、mapping情報に該当しないnull値で返すようにしました。

    こちらの認識で間違いありません。
    あまり関係ないかもしれませんが、貼って頂いたJavaScriptはfor文の位置がおかしい気がします。ボタンをクリックしてからファイル数分のリクエストを飛ばすのであれば、`function() {`の後にくるのではないでしょうか。

    ここは未知の領域なのですが、全てのリクエストが全くの同時に飛ぶとダウンロードができないのかもしれません。一時的にajaxのasyncパラメータをfalseにして同期通信で試してもらえないでしょうか。また、多少ディレイ(遅延)とかけるとかしないとだめなのかもしれません。

    よろしくお願いします。

    キャンセル

  • 2015/07/13 23:47

    こんばんは。

    確認が遅くなりまして、申し訳ありません。

    for文をfunction(){}の中に入れますと、ループ変数iを正常に参照できなかったため、外へ出して記述を行いました。
    また、同期通信、遅延も行ってみたのですが、ダウンロードは1回しか行われませんでした。

    画面上でボタンを数回押してダウンロードを繰り返すことと、リクエストを複数回送ることは同じことではないのでしょうか?
    IEの同時最大接続数なども考え、レジストリを設定して試してみたのですが、動作は変わりませんでした。
    ネット上でiframeを指定しての複数ダウンロードがMSのセキュリティ対策によりできなくなったとあったのですが、それを考慮しても、IEでの同時最大接続数が6であれば、6ファイルは同時にダウンロードできるのではないかと思って実装したのですが、成果を挙げることができませんでした。

    実行できない理由など、お心当たりがありましたら、ご教授いただけますでしょうか。

    繰り返しとなり申し訳ありません。
    以上、宜しくお願い致します。

    キャンセル

  • 2015/07/14 20:27 編集

    コメントを移動しました。

    キャンセル

checkベストアンサー

+1

こんにちわ。
申し訳ありませんが、コメントではコードハイライトが使えないので、また別で起こしました。
ChromeとIEで挙動が違うとのことでしたので少し調べました。

レスポンスのContentTypeHeaderにセットする内容で、挙動が変わるようです。
都合のよいものは見つけられませんでした。

このアプローチの仕方では、User-AgentContentTypeHeaderにセットするものを切り替えるといった方法でしか対応が不可能かもしれません。
eripongさんからご提示頂いている方法もご検討ください。
以上、よろしくお願いいたします。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <button id="btn">クリック!</button>
  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
  <script>
    $(function(){
        $('#btn').click(function(){
            for (var i=0; i<3; i++) {
                var ifrm = '<iframe style="display:none" src="http://localhost:8080/test/Download" />';
                $(ifrm).appendTo('body');
            }
        });
    });
  </script>
</body>
</html>

package test;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;

public class DownloadServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        InputStream inStream = new FileInputStream("c:\\test.txt");
        IOUtils.copy(inStream, resp.getOutputStream());

        // Chrome:3回DL IE:1回DL
//        resp.setContentType("text/plain");
//        resp.setHeader("Content-Disposition", "attachment; filename=\"test.txt" + "\"");

        // Chrome:3回DL IE:1回DL
//        resp.setContentType("application/pdf");
//        resp.setHeader("Content-Disposition", "attachment; filename=\"test.txt" + "\"");

        // Chrome:無反応 IE:無反応
//        resp.setContentType("text/plain");
//        resp.setHeader("Content-Disposition", "filename=\"test.txt" + "\"");

        // Chrome:無反応、IE:3回DL
//        resp.setContentType("application/pdf");
//        resp.setHeader("Content-Disposition", "filename=\"test.txt" + "\"");

        System.out.println("動いた");
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/16 06:45

    おはようございます。

    記載していただいた方法で実現することができました。
    attachment部分を消してもよいのだとは知らず、また、ヘッダー部によって各ブラウザの挙動が異なる点についても気がつきませんでした。

    記載していただいた方法でIE8 ,IE9で動作確認を行ったのですが、どちらも確認がとれました。

    解決までお付き合いくださいまして、本当にありがとうございました。

    キャンセル

+1

間違ってコメントの内容を投稿してしまいました。
ちょっと調べたので別の回答で上書きしておきます。

ここを見ると、
IEでも複数ファイルダウンロードできた、とあります。
これは使えないでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/15 01:09 編集

    調べていただきまして、ありがとうございます。

    提示していただいたページを参考に実施してみたのですが、対象がzipである場合はIE、chromeの両方でダウンロードができたのですが、対象がテキストである場合、両方のブラウザでダウンロードが実施されませんでした。
    拡張子によって挙動が異なるようです。

    対象がzipである場合、この方法でならweblogic+IEでもダウンロードできるというのは、ご提示いただいたサイトにあるようにContent-Dispositionを指定するからということなのでしょうか。
    この事象は、個々でダウンロードを行った場合と何が違うのでしょう?IEでファイルを一つずつダウンロードする場合は通知バーはきちんと個別に表示されると思うのですが......

    以上、宜しくお願い致します。

    キャンセル

0

こんにちは。
試しに作った複数ファイルをダウンロードさせるだけのサンプルソースを添付しますので、
レスする形ではなく新たに起こしました。
同じファイルのままですが、複数ファイルのダウンロードができました。

iframeをファイル毎に別に用意してやらないと、ファイル数分のダウンロードリクエストが飛ばないようです。この辺が動かない理由ではないでしょうか。

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>
<body>
  <button id="btn">クリック!</button>
  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
  <script>
    $(function(){
        $('#btn').click(function(){
            for (var i=0; i<3; i++) {
                var ifrm = '<iframe id="ifrm" style="display:none" src="http://localhost:8080/schedule/Download" />';
                $(ifrm).appendTo('body');
            }
        });
    });
  </script>
</body>
</html>

ご参考になればと思います。
以上、よろしくお願いいたします。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/14 23:45

    こんばんは。

    eripong様、unishakoooo様、ご意見いただきましてありがとうございます。
    現在のソースは下記となっています。

    【画面1】
    <script>
    $(function(){
    $('#bttn').click(function(){
    for (var i=0; i<3; i++) {
    var ifrm = '<iframe id="ifrm" style="display:none" src="ダウンロード用jsp?FILE=ファイル名" />';
    $(ifrm).appendTo('body');
    }
    });
    });
    </script>
    <body>
    .....
    <button type="button" id="bttn">botton</button>
    .....
    </body>

    【ダウンロード用jsp】
    <% String fileName = (String)request.getParameter("FILE"); %>
    <% if (fileName != null && fileName != "") { %>
    <script language="Javascript">
    function doDownload() {
    document.form.action="ダウンロード用アクション";
    document.form.submit();
    }
    </script>
    <% } else { %>
    <script language="Javascript">
    function doDownload() {
    }
    window.close();
    </script>
    <% } %>
    <body onload="doDownload()">
    </body>

    ダウンロード用のJavaメソッドでは、OutPutStreamにファイルデータを設定し、write()を実行しています。

    上記を用いて処理を実行した場合、forループでまわした件数分、Httpステータスは200で返却されていることをアクセスログから確認しています。

    また、weblogic+IE11でも同様にダウンロードができないことを確認しています。
    同じソースで、weblogic+chromeでは複数ダウンロードは正常に行えました。

    weblogic+IEの組み合わせが駄目だということなのでしょうか。

    以上、宜しくお願い致します。

    キャンセル

  • 2015/07/14 23:58

    unishakooooさん、了解です。
    たまたま一緒でないと、環境を合わせるのは難しいですよね。

    kurageさん、ソースコード投稿ありがとうございます。
    同じソースでchromeで実行できるなら、組み合わせというより
    IEの問題と考えて良いと思います。

    キャンセル

  • 2015/07/14 23:59

    間違って回答にコメントしてしまったのでそちらは無視してください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る