www.dextsolution.com
DEXTUPLOAD
X5
製品の説明 > 圧縮ダウンロード（ASP.NET）

# 圧縮ダウンロード（ASP.NET）

DEXTUploadX5バージョン1.3.0.0から圧縮ダウンロードに対応しました。 圧縮ダウンロードはダウンロードを一つの圧縮ファイルにまとめるダウンロードです。

1つ注意すべき点は、ファイルを圧縮する役割は、サーバーが担当しているものであり、DEXTUploadX5製品でファイルを圧縮する機能を持っているわけではない。DEXTUploadX5はダウンロード対象のvindex属性値をサーバーに転送する。サーバーはvindex値を持って圧縮する対象を選定して1つの圧縮ファイルを生成することになる。圧縮ファイルが作成されると、そのファイルをダウンロードすることができるパスをクライアントに返し、DEXTUploadX5がダウンロードパスを受け、再起動するように実装されている。

サーバーは、ファイルを圧縮することができる機能を持っている必要がありますが、いくつかの圧縮ライブラリを使って機能を実装することができますが、ASP.NET環境であれば、.NET Framework 4.5からサポートするZipArchiveクラスを使用してファイルを圧縮することができる。

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

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

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

  仮想ファイルを登録するには、addVirtualFile関数を使用するかaddVirtualFileList関数を使用して、jsonオブジェクトの形式で登録される。

  - 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 }
      ]);

  シングル/マルチファイルのダウンロードとは異なり、圧縮ダウンロードを使用する場合はurl（またはdownUrl）属性を設定する必要がない。圧縮ダウンロードはファイルを圧縮して、そのダウンロードパスを返す役割を担うアドレスのみが必要である。したがって、それぞれの仮想ファイルごとに設定したurl（またはdownUrl）属性は、圧縮ダウンロードは影響を及ぼさない。

圧縮パスを設定する

  ダウンロード対象を仮想ファイルに登録する作業が終わったら、圧縮を担当するパスを設定ヘジュオヤする。圧縮パスはsetCompressURLメソッドを使用して一度だけ登録すればよい。

  パスは、スキーマ（http、https）で始まるWeb URLべきである。

      function onDX5Created(id) {
        var dx = dx5.get(id);

        dx.addVirtualFile({ vindex: "IDX0001", name: "virtual_file.txt", size: 12345 });
        ...
        dx.addVirtualFile({ vindex: "IDX0005", name: "cosmos (empty space) 195779.jpg", size: 195779 });

        // 圧縮を処理するパスを設定する。
        dx.setCompressURL("http://domain/path/compress.ashx");
      }

ボタンの接続

  仮想ファイルと圧縮ダウンロードパスの設定が完了したら、downloadCompressedメソッドを使用して圧縮のダウンロードを開始すればよい。

      <button type="button" onclick="compress('component-id');">圧縮ダウンロード</button>
      <script>
      function compress(id) {
        // フラグの値に基づいて、ターゲットを変えて圧縮ダウンロードを実行する。
        // AUTO：全仮想ファイルを圧縮ダウンロードする。
        // SELECTED：選択された仮想ファイルを圧縮ダウンロードする。
        // CHECKED：チェックされた仮想ファイルを圧縮ダウンロードする。
        dx5.get(id).downloadCompressed("AUTO");
      }
      </script>

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

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

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

サーバー側の処理（ASP.NET）

  compress.ashxでZipArchiveクラスを使用して圧縮タスクを処理することができる。

  DEXTUploadX5はdownloadCompressedメソッドを呼び出すと、vindex属性値をコンマ（、）文字を区切り文字とするリストの文字列を生成し、この値を「DEXTUploadX5_VIndexes」の名前が与えられてたフォームデータをPOST形式でsubmitする。

      // DEXTUploadX5_VIndexesフォーム名から圧縮する対象の仮想インデックスのセットを得ることができる。
      var data = context.Request.Form["DEXTUploadX5_VIndexes"] ?? string.Empty;
      var vindexes = data.Split(',');
      var targets = new List<string>();

      foreach (string index in vindexes)
      {
          if (index.Equals("IDX0003")) targets.Add(context.Server.MapPath("~/files/attach/bridge_509147.jpg"));
          else if (index.Equals("IDX0004")) targets.Add(context.Server.MapPath("~/files/attach/beach_239826.jpg"));
          else if (index.Equals("IDX0005")) targets.Add(context.Server.MapPath("~/files/attach/cosmos (empty space) 195779.jpg"));
      }

      var zipPath = Path.GetTempFileName();

      // .NET Framework 4.5からサポートするZipArchiveを利用して、圧縮ファイルを生成する。
      using (var fs = new FileStream(zipPath, FileMode.Create))
      using (var za = new ZipArchive(fs, ZipArchiveMode.Create, false, System.Text.Encoding.UTF8))
      {
          foreach (string path in targets)
          {
              za.CreateEntryFromFile(path, Path.GetFileName(path));
          }
      }

      // 例ではなく、実際の状況では、セッションやデータベースなどの他のストレージ方式を利用して、
      // 実際にダウンロードを実行する必要がハンドラ（zip-download.ashx）で圧縮ファイルのパスを取得することができるよう処理しなければならない。
      // FileRepositoryとFileEntityクラスは、サンプルの構成と理解を助けるために作成された。

      FileRepository.Clear();
      var key = FileRepository.Add(new FileEntity {
          Path = zipPath,
          MimeType = "application/x-zip-compressed",
          FileName = string.Concat(Path.GetFileNameWithoutExtension(zipPath), ".zip")
      });

      // 圧縮されたファイルをダウンロードすることができるハンドラパスを生成する。
      UriBuilder b = new UriBuilder(context.Request.Url);
      b.Path = VirtualPathUtility.ToAbsolute("~/download/zip-download.ashx");
      b.Query = string.Concat("key=", key);

      // 圧縮されたファイルをダウンロードすることができるパスを応答データに乗せて、クライアントに渡さなければならない。
      context.Response.ContentType = "text/plain";
      context.Response.Write(b.ToString());

  対象のファイルを圧縮した後、圧縮ファイルをダウンロードしなければならない。前の応答データに記録された値がすぐに圧縮ダウンロードをダウンロードすることができ、サーバー側のパスであり、これは、次のような方法で実装することができる。

      var key = context.Request.QueryString["key"] ?? string.Empty;
      var entry = FileRepository.Get(key);

      if (entry != null)
      {
          // DEXTUpload.NET Professional製品を使用してダウンロードを実行する。
          using (var dext = new FileDownload())
          {
              dext.Download(entry.Path, entry.FileName, new DownloadOption {
                  // ダウンロードをした後、圧縮ファイルは、無意味なファイルであるため、削除するようにする。
                  RemoveAfterDownloading = true,
                  // 圧縮ファイルは、各リクエストごとに生成されるため、クライアントのキャッシュを使用しないようにする。
                  UseClientCache = false,
                  // application/x-zip-compressed
                  MimeType = entry.MimeType
              });
          }
      }
      else
      {
          throw new HttpException(404, "The zip file not found.");
      }

サーバー側の処理（ASP.NET MVC）

  次のアドレスに圧縮処理を要求するものとする。

      function onDX5Created(id) {
        var dx = dx5.get(id);

        dx.addVirtualFile({ vindex: "IDX0001", name: "virtual_file.txt", size: 12345 });
        ...
        dx.addVirtualFile({ vindex: "IDX0005", name: "cosmos (empty space) 195779.jpg", size: 195779 });
        // 圧縮を処理するパスを設定する。
        dx.setCompressURL("http://domain/DownloadSample/Compress");
      }

  サーバーは、DownloadSampelControllerのCompressメソッドにZipArchiveクラスを使用して圧縮処理を実行する。

      [HttpPost]
      public ActionResult Compress([Bind(Prefix = "DEXTUploadX5_VIndexes")] string data)
      {
          var vindexes = data.Split(',');
          var targets = new List<string>();

          foreach (string index in vindexes)
          {
              if (index.Equals("IDX0003")) targets.Add(Server.MapPath("~/files/attach/bridge_509147.jpg"));
              else if (index.Equals("IDX0004")) targets.Add(Server.MapPath("~/files/attach/beach_239826.jpg"));
              else if (index.Equals("IDX0005")) targets.Add(Server.MapPath("~/files/attach/cosmos (empty space) 195779.jpg"));
          }

          var zipPath = Path.GetTempFileName();

          // .NET Framework 4.5からサポートするZipArchiveを利用して、圧縮ファイルを生成する。
          using (var fs = new FileStream(zipPath, FileMode.Create))
          using (var za = new ZipArchive(fs, ZipArchiveMode.Create, false, System.Text.Encoding.UTF8))
          {
              foreach (string path in targets)
              {
                  za.CreateEntryFromFile(path, Path.GetFileName(path));
              }
          }

          // 例ではなく、実際の状況では、セッションやデータベースなどの他のストレージ方式を利用して、
          // 実際にダウンロードを実行する必要がパスで圧縮ファイルのパスを取得することができるよう処理しなければならない。

          ...

          // 圧縮されたファイルをダウンロードすることができるパスを応答データに乗せて、クライアントに渡さなければならない。
          return Content(Url.Action("DownloadZip", new { id = key }), "text/plain", Encoding.UTF8);
      }

  対象のファイルを圧縮した後、圧縮ファイルをダウンロードしなければならない。前の応答データに記録された値がすぐに圧縮ダウンロードをダウンロードすることができ、サーバー側のパスであり、これは、次のような方法で実装することができる。

      [HttpGet]
      public ActionResult DownloadZip(string id)
      {
          var entry = FileRepository.Get(id);

          if (entry == null)
          {
              throw new HttpException(404, "The zip file not found.");
          }
          else
          {
              // ダウンロードをした後、圧縮ファイルを削除する機能は提供しない。
              return File(entry.Path, "application/x-zip-compressed", entry.FileName);
          }
      }

圧縮ダウンロードの制限および注意点
  - DEXTUploadX5は圧縮ダウンロードするための一連の作業過程を支援することで、独自のファイルを圧縮する機能を持っていない。

  - 圧縮ダウンロードは、サーバー側でファイルを圧縮する過程が存在する。ファイルを圧縮するのに必要とされる時間が長くなる場合、意図しない問題が発生することができる。

    ファイルを圧縮する作業は、サーバーのリソース（CPU、I / O）を大幅に消費する作業であるため、サイズが大きいファイルや圧縮ファイルの対象となるファイルの数が多い場合、サーバーにかなりのオーバーヘッドが発生するので、 、状況に応じて、ファイル圧縮処理を待っている時間が長くなることがあり、これは、セッションが途切れる問題がもたらさたり、サービス自体が停止される重大な問題につながることができる。したがって、圧縮のダウンロードをするための政策的制限を確立した後、機能を使用することをお勧めします。

  - 圧縮がサーバーで実行中DEXTUploadX5は進行ウィンドウが表示されますが、圧縮されたファイルをダウンロードするときは、単一​​のファイルのダウンロードに移行されるので、ダウンロードプロセスの独自の進行状況ウィンドウは提供されない。

  - macOS Safariブラウザで圧縮ダウンロードを実行すると、ブラウザのポップアップブロック機能によりダウンロード処理が必要にしていないことがあります。したがって、サービスしようとするサイトのポップアップをブロックするSafariの設定を事前に解除する必要がある。

    macOS Safariブラウザは、ファイルをダウンロードした後、「安全なファイルを開く」機能により、zipファイルを解放しまうため、zipファイルのままダウンロードができない場合があります。もしzipファイルが自動的に解ける現象を防ぎたい場合、Safariの環境設定の[全般]タブで、その設定をチェック解除すればよい。