www.dextsolution.com
DEXTUPLOAD
X5
製品の説明 > ファイルのダウンロード

# ファイルのダウンロード

一般的に、ブラウザがサーバにGET / POSTリクエストをすると、サーバは応答データを返すために、この応答データがブラウザが直接解釈して画面に表現することができない形式である場合には、この応答データをファイルとしてダウンロードする。Anchor（a）タグに設定されたハイパーリンクの値を例にとると、ブラウザが解釈することができる画像（jpg）ファイルである場合、新しいウィンドウ（またはタブ）、または現在のウィンドウに画像が表示されるが、zipファイルの場合には、すぐにダウンロードを実行することを見ることができる。もしjpgファイルを開かずに、ディスクに直接ダウンロードするには、ブラウザ自体の機能（コンテキストメニュー - 名前を付けて保存）に依存したり、サーバーからブラウザが強制的にダウンロードできるようにするレスポンスヘッダを載せなければならない。

注意）macOSでダウンロードファイルが画像であるか、zipの場合、自動的に接続プログラムを実行されたりする。HTML5には、対象の型（mime type）に関係なく、強制的にファイルをダウンロードできるようにする属性が新たに追加された。しかし、すべてのブラウザでは、この機能をサポート（2016年初め基準）していないため、HTML、またはJavaScriptだけを持ってファイルをディスクにダウンロードすることができない。

DEXTUploadX5からファイルをダウンロードしようとする場合、ブラウザの特性によって影響を受けるため、異なるブラウザでも同じようにファイルがダウンロードされる（開かれない）ようにするには、サーバーのレスポンスヘッダーを使用する必要があります。

ダウンロードアイテムを登録する

  DEXTUploadX5はダウンロードする項目を必ず仮想ファイルに登録する必要がある。

  仮想ファイルは、ユーザーのローカルPC上に存在せず、実体のない仮想のファイルをいう。つまり、実際にローカルに存在しないファイルなので、ファイルのアップロード先ではない。一般的に、仮想ファイルは既にアップロードされたファイルに関する情報を残す目的で使用したりする。（サーバーに存在するファイルと呼ばれる表示）

  仮想ファイルを登録するには、addVirtualFile関数を使用するかaddVirtualFileList関数を使用する。

  - vindex：仮想ファイルを区分する唯一のキーとして、どのような形式でも構いませんが、重複してはならない。（必須項目）
  - name：仮想ファイルの名前である。（必須項目）
  - size：仮想ファイルのサイズであり、byte単位を使用する。（必須項目）
  - lock：ロック状態がtrueの場合、ファイルを削除することができない。

      var dx = dx5.get(id);
      // 個別に登録するときに
      dx.addVirtualFile({ vindex: "IDX0001", name: "virtual_file.txt", size: 12345 });
      dx.addVirtualFile({ vindex: "IDX0002", name: "locked-virtual_file.txt", size: 45678, lock: true });
      dx.addVirtualFile({ vindex: "IDX0003", name: "cosmos.jpg", size: 195779 });

      // 複数のを一度に登録するとき
      dx.addVirtualFileList([
        { vindex: "IDX0001", name: "virtual_file.txt", size: 12345 },
        { vindex: "IDX0002", name: "locked-virtual_file.txt", size: 45678, lock: true },
        { vindex: "IDX0003", name: "cosmos.jpg", size: 195779 }
      ]);

  仮想ファイルがダウンロード対象となるにjson属性中url属性（またはdownUrl属性）が設定されてなければならない。

      // ダウンロードパス情報がなくてダウンロードすることができない、仮想ファイルである。
      dx.addVirtualFile({ vindex: "IDX0001", name: "virtual_file.txt", size: 12345 });
      // ダウンロードパスがあればダウンロードすることができる。
      dx.addVirtualFile({ vindex: "IDX0003", name: "bridge_509147.jpg", size: 509147, url: "http://domain/file/attach/bridge_509147.jpg" });
      dx.addVirtualFile({ vindex: "IDX0003", name: "bridge_509147.jpg", size: 509147, url: "http://domain/common-download.do?key=FID0001" });

  url（またはdownUrl）属性の値は、必ずスキーマ（http、https）で始まるWeb URLべきである。URLにハングルや特殊文字が入った場合には、対象をできない検索したり、ダウンロードが失敗する場合がある。（必ずないのではなく、ブラウザの種類やバージョンごとに差があることができる。）このような場合、多言語と特殊文字が使用されている区間をencodeURIComponent JavaScript関数を使用してエンコードをすればよい。

      dx.addVirtualFile({
        vindex: "IDX0003",
        // エンコード不要
        name: "bridge_509147.jpg",
        size: 509147,
        // エンコードが必要
        downUrl: "http://domain/file/attach/" + encodeURIComponent("bridge_509147.jpg")
      });

ボタンの接続

  DEXTUploadX5コンポーネントはurl(またはdownUrl)が設定されたアイテムに対してのみダウンロードボタンを表示します。 ターゲットに表示されるダウンロードボタンを使用せず、外部のHTMLボタンを使用したい場合は、スクリプトを使用してコンポーネントの機能を接続する必要があります。

      <button type="button" onclick="download('component-id');">ダウンロード</button>
      <script>
      function download(id) {
        // フラグの値に基づいてダウンロードを実行する。
        // AUTO：最初の仮想ファイルをダウンロードする。
        // SELECTED：選択された対象の中の最初の仮想ファイルをダウンロードする
        // CHECKED：チェックされた対象の中の最初の仮想ファイルをダウンロードする。
        dx5.get(id).download("AUTO");
      }
      </script>

  複雑なスクリプトを使用せずに、コンポーネントのロード時に自動的にバインド機能も付属しています。

      <button type="button" id="btn-down-auto">ダウンロード</button>
      <button type="button" id="btn-down-selected">選択ダウンロード</button>
      <button type="button" id="btn-down-checked">チェックダウンロード</button>
      <script>
        dx5.create({
          ...,
          // コンポーネントが作成されるとき、ファイルのダウンロード機能が自動的に接続するようにする。
          btnDownloadAuto: "btn-down-auto",
          btnDownloadSelected: "btn-down-selected",
          btnDownloadChecked: "btn-down-checked"
        });
      </script>

  自動バインディング機能は非常に便利が、複雑な機能を実装するには適さないことがあります。

サーバー側の処理

      // ダウンロードする対象がウェブアドレスにさらされている場合、
      { vindex: "IDX0003", name: "bridge_509147.jpg", size: 509147, url: "http://domain/files/attach/bridge_509147.jpg" }

  ダウンロードしようとする対象がウェブアドレスを持っている場合は、対象を呼び出したとき、ダウンロードが可能なようにサーバーでは、応答ヘッダーに「Content-Disposition：attachment "を追加すればよい。

  ダウンロードするためのWebサーバーやWAS星応答ヘッダーの設定方法は、本書では提供しない。

  もし対象がウェブアドレスを持っていないか、または、URL、秘匿が必要な場合は、Webアプリケーションを使用してダウンロードすることができるようにサービスを設定する必要がある。

      // ダウンロードする対象がウェブアドレスに存在しないか、URL、秘匿処理のために、Webアプリケーションを使用する場合は、
      { vindex: "IDX0003", name: "bridge_509147.jpg", size: 509147, downUrl: "http://domain/files/service/common-download.do?key=FID0001" }

  次は、Java JSPやサーブレット環境でDEXTUploadNJ製品を使用してサービスを実装した場合である。指定されたマッピングサーブレット（JSPも可能）でFileDownloadクラスを使用してダウンロードを処理することができる。

      # サーバー側の設定である。
      File target = null;

      String key = request.getParameter("key");

      if (key.equals("FID0001")) target = new File(fileRoot, "bridge_509147.jpg");
      else if (key.equals("FID0002")) target = new File(fileRoot, "beach_239826.jpg");
      else if (key.equals("FID0003")) target = new File(fileRoot, "cosmos (empty space) 195779.jpg");

      if (target == null  || target.exists() == false || target.isFile() == false) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found.");
        return;
      }

      try {
        // FileDownloadオブジェクトを生成する。
        FileDownload dextnj = new FileDownload();
        // エンコードをUTF-8に設定する。
        response.setCharacterEncoding("UTF-8");
        // ファイルを添付ファイル形式でダウンロードする。
        dextnj.download(request, response, target);
      } catch (Exception e) {
        throw new ServletException(e);
      }

  次は、Java Spring Webフレームワーク環境でDEXTUploadNJ製品を使用してサービスを実装した場合である。指定された要求にマップされたコントローラのメソッドでDEXTUploadNJFileDownloadViewクラスを使用してダウンロードを処理することができる。

      # サーバー側の設定である。
      File target = null;

      String fileRoot = request.getSession().getServletContext().getRealPath("/files/attach");

      if (key.equals("FID0001")) target = new File(fileRoot, "bridge_509147.jpg");
      else if (key.equals("FID0002")) target = new File(fileRoot, "beach_239826.jpg");
      else if (key.equals("FID0003")) target = new File(fileRoot, "cosmos (empty space) 195779.jpg");

      // エンコードをUTF-8に設定する。
      response.setCharacterEncoding("UTF-8");

      if (target == null  || target.exists() == false || target.isFile() == false) {
        response.sendError(HttpServletResponse.SC_NOT_FOUND, "Not found.");
        return null;
      } else {
        // DEXTUploadNJFileDownloadViewビュークラスを使用してファイルをダウンロードすることができる。
        DEXTUploadNJFileDownloadView dextnj = new DEXTUploadNJFileDownloadView(target);
        return new ModelAndView(dextnj);
      }

複数のファイルのダウンロード（1.1.0.0版から対応）

  前述のダウンロード方法は、画面の中のダウンロードアイコンをクリックするか、またはdownload、downloadByIdメソッドを使用して一本ずつファイルをダウンロードする方法を説明したものである。

  HTML5はSandbox問題により、ローカルリソースへのアクセスが容易なプラグイン技術を使用せずに、複数のファイルをダウンロードすることができないのが一般的な考えである。ただし、ファイルの容量に制限を置き、ダウンロードパスの設定をブラウザに任せたら、順次複数のファイルをダウンロードする複数のファイルのダウンロード機能を、純粋なブラウザ技術だけで実装することができる。

  複数のファイルのダウンロードは、ダウンロードを実行するためのアイコンが別々に存在しないので、downloadメソッドを直接呼び出して使用する。

  downloadメソッドの2番目の値がtrueの場合、複数のファイルをダウンロードする方法でのダウンロードタスクを実行する。

      <button type="button" onclick="download('component-id');">ダウンロード</button>
      <script>
      function download(id) {
        // フラグの値に基づいてダウンロードを実行する
        // AUTO：すべての仮想ファイルをダウンロードする。
        // SELECTED：選択された対象の中の仮想ファイルの両方をダウンロードする。
        // CHECKED：チェックされたターゲットの中の仮想ファイルの両方をダウンロードする。
        dx5.get(id).download("AUTO", true);
      }
      </script>

  マルチモジュールで複数のファイルをダウンロードする方法を使用する場合、サーバーのコンポーネントを使用する場合は、キャッシュオプションの調整が必要である。

  サーブレット（JSP）の環境でFileDownloadクラスを使用してダウンロードを処理するとき、

      # サーバー側の設定である。
      ...
      // FileDownloadオブジェクトを生成する。
      FileDownload dextnj = new FileDownload();
      // エンコードをUTF-8に設定する。
      response.setCharacterEncoding("UTF-8");
      // dextnj.download(request, response, target);
      // 単一ファイルのダウンロードではなく、複数のファイルのダウンロードでは、キャッシュを使用してはならない。（useClientCacheパラメータ値をfalseに設定）
      dextnj.download(request, response, target, target.getName(), "application/octet-stream", false, false);

  JavaのSpring Webフレームワーク環境でDEXTUploadNJFileDownloadViewクラスを使用する場合は、次のとおりである。

      # サーバー側の設定である。
      ...
      // DEXTUploadNJFileDownloadViewビュークラスを使用してファイルをダウンロードすることができる。
      DEXTUploadNJFileDownloadView dextnj = new DEXTUploadNJFileDownloadView(target);
      // キャッシュをfalseに設定する。
      dextnj.setUseClientCache(false);
      return new ModelAndView(dextnj);

  ファイルダウンロードは、ブラウザのメモリ管理の問題により、ダウンロードするファイルのサイズに制限を設けている。デフォルト値は100MBであり、ファイルサイズをそれ以上許可するには、setLimitMultiDownloadSizeメソッドを使用して制限サイズを変更する必要がある。

  HTML5の機能を使用してファイルを連続的にダウンロードする場合、一時的にダウンロード対象をメモリにロードするため、動画ファイルのような大容量ファイルはブラウザのメモリに負荷をかけ、深刻な場合にはクラッシュを引き起こす可能性があります。setLimitMultiDownloadSizeメソッドはダウンロードが許可されるファイルのサイズを変更するものであり、ブラウザのメモリ性能を向上させるものではありません。

      // ダウンロードサイズ制限を300MBに設定する。
      dx.setLimitMultiDownloadSize(1024 * 1024 * 300);

シングル、マルチファイルのダウンロードの共通点と相違点

  シングル | 複数の
  --- | ---
  ダウンロードパス（ローカルPC）は、ブラウザの設定に基づいて決定されるため、コンポーネントで、これを変更することができない。
  ダウンロードパスに同じファイル名を持つファイルがある場合は、ブラウザが自動的にsuffix（番号のような）を付ける。
  バージョン4.0.0.0以降、ダウンロード可能なファイル容量に制限（デフォルト値100MB）が設けられているが、制限を解除してもブラウザメモリに負荷はかからない。 | ダウンロード可能なファイル容量に制限（デフォルト値100MB）が存在する。
  対象をダウンロード（GET）の前に、HEADリクエストを事前に送って、ファイルの存在の有無を確認する。 | マルチファイル・ダウンロードでは、ファイルの存在を確認するためのHEADリクエストは送信されません。(バージョン3.8.0.0から、マルチファイルダウンロードもHEADリクエストを送信するようになりました)。
  対象の種類に応じて添付の形でダウンロードならないことがあるので、サーバーやサーバーコンポーネントを使用して、Content-Disposition：attachmentレスポンスヘッダを設定する必要がある。 | 複数のファイルのダウンロードは、Content-Dispositionレスポンスヘッダの設定にかかわらず、対象をダウンロードすることができる。
  ダウンロード進行状況ウィンドウを提供しない。 | ダウンロードの進行ウィンドウを提供する。 ブラウザが最終的にファイルを保存するステップ（制御がない）が存在するため、ダウンロードが完了した場合でも、ブラウザでダイアログをポップアップ表示したり、一時ファイルをコピーするなどの作業があることができる。
  HTML5をサポートするすべてのモダンブラウザ（Edge、IE、Safari、Chrome、Firefox、Opera）でサポートされています。 iOSおよびiPadでは、Safari（バージョン13以降）のみがシングルファイルダウンロードをサポートしています。 | macOSでは、Safari 10.1以降がサポートされています。 iOSおよびiPadでは、Safariのバージョン17以降のみがサポートされ、ファイルの欠落を避けるためにダウンロードするファイルが少ない場合（10個以下）のみサポートされます。
  ボタンと自動的にバインドする機能をサポートします。 | 複数のファイルをダウンロードするにはボタンと自動的にバインドする機能をサポートしていない。