none
データベースに保存したファイルをダウンロードする際、更新日を指定したい RRS feed

  • 質問

  • はじめまして。さとと申します。

     

    開発環境: Visual Web Developer 2008、SQLServer2000

     

    ファイルをデータベースに保存し、保存したファイルをダウンロードする仕組みを構築しました。

    当然ながら、データベースからファイル出力する際、そのファイルの最終更新日がファイル出力した日に

    変更されます。

     

    ファイルをデータベースに保存する際、GetLastWriteTimeでそのファイルの最終更新日を記録し、

    ファイルをデータベースから取り出す際にその更新日を付加してファイル出力したいのですが方法がよく分かりません。

     

    ファイル出力の際、下記構文で出力しております。

      If objRs.Read() Then
                Response.ContentType = CType(objRs.Item(0), String)
                Response.BinaryWrite(CType(objRs.Item(1), Byte()))
                Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(objRs.Item(2)))
      End If

    objDb.Close()

    Response.End()

     

    この処理の後に、LastWriteTimeでファイルに更新日を設定するのだと思うのですが、どのように指定すれば

    いいのでしょうか?

     

    ヒントをお願いします。

     

    以上、よろしくお願いします。

    2008年11月20日 0:28

回答

  •  さと581402 さんからの引用

    この処理の後に、LastWriteTimeでファイルに更新日を設定するのだと思うのですが、どのように指定すれば

    いいのでしょうか?

     

    ヒントをお願いします。

     

    WindowsアプリケーションであればLastWriteTimeで日付の更新は可能ですが、Webアプリケーションの場合、すでにクライアントにファイルがダウンロードされてしまっているので更新は出来ません。

     

    ただし、Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode

    にファイルの更新日付の情報を入れる事ができれば可能だと思いますが、出来るかどうか不明です。

    (うろ覚えですが、RFCで定義されていた気はするのですが…)

     

    一度、そちらの観点から調べてみてはどうでしょうか?

     

    2008年11月20日 1:11
  • 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものをダウンロードする、という手はあるかと思います。
    ただ、同時に操作された場合の考慮をうまく考えておかないといけませんね。

     

    2008年11月20日 2:15
  • 私も試してみましたがダメでした。日付をRFC822形式にしてみてもダメでした。なぜだろう? くやしい・・・。

    どっとねっとふぁんさんが書かれた方法もありだと思いますが、注意しなければならないのは、例えばある会員サイトで、その文書へのリンクが漏れると会員サイトにログインしなくてもダウンロードできるようになってしまうことです。

    2008年11月21日 4:19
    モデレータ
  •  どっとねっとふぁん さんからの引用

    一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものをダウンロードする、という手はあるかと思います。

    そうしたところで、結局、ブラウザ次第なんじゃないのかな

    # 私、何か勘違いしてるのかなぁ・・・
    2008年11月21日 4:59
  •  

    > そうしたところで、結局、ブラウザ次第なんじゃないのかな

    自分もそう思います。

    例として正しいかどうかわかりませんが、FTPでファイルをGETやPUTしてもファイルの更新日付は変わってしまいますし。

     

    もし、どうしてもサーバーの日付と合わせる必要があるのであれば、ファイルをダウンロードさせるActiveXコントロールを作成して、それで日付を更新する方法はありますけど。
    (セキュリティやActiveXコントロールをインストールする必要があるため、あまり勧められません)

     

    今思いつきましたけど、サーバー側でファイルをzipやlhaで圧縮し、クライアント側でダウンロード後、それを展開すれば更新日時はサーバーと同じになると思いますけど、どうでしょう?

    2008年11月21日 8:04
  •  さと581402 さんからの引用

    ファイルをデータベースに保存する際、GetLastWriteTimeでそのファイルの最終更新日を記録し、

    ファイルをデータベースから取り出す際にその更新日を付加してファイル出力したいのですが方法がよく分かりません。

     

    ファイル出力の際、下記構文で出力しております。

      If objRs.Read() Then
                Response.ContentType = CType(objRs.Item(0), String)
                Response.BinaryWrite(CType(objRs.Item(1), Byte()))
                Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(objRs.Item(2)))
      End If

    objDb.Close()

    Response.End()

     

    この処理の後に、LastWriteTimeでファイルに更新日を設定するのだと思うのですが、どのように指定すれば

    いいのでしょうか?

     

    みなさんのレスから、結論としては、

     

    データベースから取り出されたバイト列データ objRs.Item(1) からファイルを
    作って、

     

    > 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものを

     

    > zipやlhaで圧縮し、

     

    その圧縮ファイルをバイト列データに変換し、Response.BinaryWrite メソッド
    で HTTP 出力ストリームに書き込み、

     

    > クライアント側でダウンロード後、それを展開

     

    ということになるようです。

     

    上記でよろしいでしょうか? > 回答者のみなさん

    2008年11月22日 4:39
  •  さと581402 さんからの引用

    でも、「3)GZipStreamでzipに圧縮。」した際に、圧縮前のファイル更新日が勝手に変更されてしまいます。

     

    今頃になって気がつきました。(汗)

     

    たぶん、FileStream で読んでくる実データのみを圧縮して送ることを考
    えていると思いますが、そもそも実データにはファイル名や更新日などの
    情報(メタデータ)は入ってないです。

     

    WinZip 等が作る zip アーカイブには、実データに加えてメタデータが含
    まれており、解凍時にメタデータを使ってファイル名や更新日時を設定し
    ているようです。

     

    という訳で、「圧縮前のファイル更新日が勝手に変更」と言うことではな
    さそうです。

     

    今回の目的を果たすには、実データに加えてメタデータも一緒に、世間一
    般に使われている解凍ツールと互換性のある zip アーカイブにして送っ
    てやる必要があるということになります。

     

    zip アーカイブを作るには、以下のサイトで紹介されている方法が役に
    立ちそうです。

     

    荒井省三のBlog: Dynamic Language SDK を使った ZIPアーカイブの使い方
    http://blogs.msdn.com/shozoa/archive/2008/09/24/how-to-zip-archive-by-using-dynamic-language-sdk.aspx

     

    例えば、ここで紹介されている「フリーのライブラリを使用する(たとえ
    ば、ここなど)。」のリンク↓

     

    The Zip, GZip, BZip2 and Tar Implementation For .NET
    http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx

     

    このライブラリを使えば、更新日時は自由に設定できますし、作った zip
    ファイルは WinZip で開けることは自分も確認済みです。圧縮するだけな
    らかなり簡単に出来ます(他の手段でも簡単かもしれませんが)。

     

    マイクロソフトのサンプルもありますが(下記サイトから入手できる)、
    これで作った圧縮ファイルは、WinZip と互換性がないです。理由は調べ
    てません(調べる前に諦めました)。

     

    Microsoft .NET Framework SDK version 2.0 Samples Download
    http://www.microsoft.com/downloads/details.aspx?FamilyID=adef80f9-1e44-4b94-be24-dff48f826ce6&DisplayLang=en

    2008年11月28日 12:30
  •  SurferOnWww さんからの引用

    みなさんのレスから、結論としては、

     

    データベースから取り出されたバイト列データ objRs.Item(1) からファイルを
    作って、

     

    > 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものを

     

    > zipやlhaで圧縮し、

     

    その圧縮ファイルをバイト列データに変換し、Response.BinaryWrite メソッド
    で HTTP 出力ストリームに書き込み、

     

    > クライアント側でダウンロード後、それを展開

     

    ということになるようです。

     

    よく考えてみると、「一度サーバ上のどこかにファイルを書き込んで、更
    新日時を変更」というステップは不要でした。

     

    以下のステップで可能です。

     

    (1) データベースからバイト列データを取り出す。

     

    (2) 既存のライブラリを利用して zip アーカイブをバイト列として作成。
      更新日時やファイル名はその時設定。

     

    (3) 作成したバイト列を Response.BinaryWrite メソッドで HTTP 出力ス
      トリームに書き込み

     

    ご参考までに、先のレスで紹介した下記のサイトから入手できるライブラ
    リを使った例をアップしておきます。

     

    The Zip, GZip, BZip2 and Tar Implementation For .NET
    http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx

     

    実行するには Bin フォルダに ICSharpCode.SharpZipLib.dll を入れてお
    く必要があります(上記のサイトから入手できます)。

     

    Code Snippet

    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Data.SqlClient" %>
    <%@ Import Namespace="System.Configuration" %>
    <%@ Import Namespace="System.IO" %>
    <%@ Import Namespace="ICSharpCode.SharpZipLib.Zip" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">

        protected void Page_Load(object sender, EventArgs e)
        {
            string connString =
                ConfigurationManager.ConnectionStrings["databaseConnectionString"].ConnectionString;
            SqlConnection connection = new SqlConnection(connString);
            string query = "SELECT filename, data FROM files WHERE id=@id";
            SqlCommand command = new SqlCommand(query, connection);
            command.Parameters.AddWithValue("@id", Convert.ToInt32(Request.QueryString["id"]));
            string filename = null;
            byte[] data = null;
           
            try
            {
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    filename = (string)reader[0];
                    data = (byte[])reader[1];
                }
            }
            finally
            {
                connection.Close();
            }

            if (filename == null || data == null)
            {
                // DB から取得できなかった場合の処置(ここでは単に return)
                return;
            }

            Response.AppendHeader("Content-Disposition",
                "attachment; filename=" + HttpUtility.UrlEncode(filename) + ".zip");
            Response.ContentType = "application/x-zip-compressed";

            byte[] zippedData = new byte[data.Length];  // 圧縮前 (data.Length) よりは小さくなるはず。
            int zippedDataLength = 0;
            using (MemoryStream memoryStream = new MemoryStream(zippedData))
            {
                using (ZipOutputStream zipOutStream = new ZipOutputStream(memoryStream))
                {
                    zipOutStream.SetLevel(9); // 圧縮度の設定。9 が最高
                    ZipEntry entry = new ZipEntry(filename);
                    entry.DateTime = new DateTime(2000, 1, 1);  // ここで更新日時を設定
                    zipOutStream.PutNextEntry(entry);
                    zipOutStream.Write(data, 0, data.Length);               
                    zipOutStream.Finish();

                    // 圧縮後のサイズを取得。Finish() の前に置くのはダメ。zipOutStream.Length はダメ。
                    zippedDataLength = (int)zipOutStream.Position; 
                    zipOutStream.Close();
                }
            }       
            Array.Resize(ref zippedData, zippedDataLength);
            Response.BinaryWrite(zippedData);
            Response.End();
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server"></asp:Label>
        </div>
        </form>
    </body>
    </html>

     

     

    2008年11月29日 9:45

すべての返信

  •  さと581402 さんからの引用

    この処理の後に、LastWriteTimeでファイルに更新日を設定するのだと思うのですが、どのように指定すれば

    いいのでしょうか?

     

    ヒントをお願いします。

     

    WindowsアプリケーションであればLastWriteTimeで日付の更新は可能ですが、Webアプリケーションの場合、すでにクライアントにファイルがダウンロードされてしまっているので更新は出来ません。

     

    ただし、Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode

    にファイルの更新日付の情報を入れる事ができれば可能だと思いますが、出来るかどうか不明です。

    (うろ覚えですが、RFCで定義されていた気はするのですが…)

     

    一度、そちらの観点から調べてみてはどうでしょうか?

     

    2008年11月20日 1:11
  • 試していませんが、filenameと同様に、creation-date、modification-date、read-dateでうまくいくかもしれません。
    CatTailさんが言われているのは、RFC2183のことだと思います。

     

    RFC 2183 インターネットメッセージの情報交流表現:Content-Dispositionヘッダーフィールド
    http://jbpe.tripod.com/rfcj/rfc2183.j.sjis.txt

    2008年11月20日 2:00
    モデレータ
  • 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものをダウンロードする、という手はあるかと思います。
    ただ、同時に操作された場合の考慮をうまく考えておかないといけませんね。

     

    2008年11月20日 2:15
  •  trapemiya さんからの引用

    試していませんが、filenameと同様に、creation-date、modification-date、read-dateでうまくいくかもしれません。

     

    modification-date のみですが、実際に試してみました。結果は何も変化な

    し(更新日時はダウンロードした日時のまま)でした。

     

    RFC 2183 の 3. Examples の個人的解釈ですが、必要がある場合、受信

    者がダウンロードしたファイルの更新日時を正しく修正できるように、実際の

    更新日時を modification-date 書いておくということのようです。(ファイル名

    の方は filename で指定された名前にすべきだそうですが)

     

    というわけで、どっとねっとふぁんさんが書かれた方法の他なさそうな気がし

    ます。

    2008年11月20日 14:22
  • 私も試してみましたがダメでした。日付をRFC822形式にしてみてもダメでした。なぜだろう? くやしい・・・。

    どっとねっとふぁんさんが書かれた方法もありだと思いますが、注意しなければならないのは、例えばある会員サイトで、その文書へのリンクが漏れると会員サイトにログインしなくてもダウンロードできるようになってしまうことです。

    2008年11月21日 4:19
    モデレータ
  •  どっとねっとふぁん さんからの引用

    一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものをダウンロードする、という手はあるかと思います。

    そうしたところで、結局、ブラウザ次第なんじゃないのかな

    # 私、何か勘違いしてるのかなぁ・・・
    2008年11月21日 4:59
  •  

    > そうしたところで、結局、ブラウザ次第なんじゃないのかな

    自分もそう思います。

    例として正しいかどうかわかりませんが、FTPでファイルをGETやPUTしてもファイルの更新日付は変わってしまいますし。

     

    もし、どうしてもサーバーの日付と合わせる必要があるのであれば、ファイルをダウンロードさせるActiveXコントロールを作成して、それで日付を更新する方法はありますけど。
    (セキュリティやActiveXコントロールをインストールする必要があるため、あまり勧められません)

     

    今思いつきましたけど、サーバー側でファイルをzipやlhaで圧縮し、クライアント側でダウンロード後、それを展開すれば更新日時はサーバーと同じになると思いますけど、どうでしょう?

    2008年11月21日 8:04
  •  karashima さんからの引用

    そうしたところで、結局、ブラウザ次第なんじゃないのかな

    # 私、何か勘違いしてるのかなぁ・・・

     

    あれ? 私も勘違いしてました。ブラウザによるかもしれません。ダウンロードしたzipの中身のファイルを確認してました。そういうわけでzipで包む方法もあるかもです。

     

    #CatTailさんが書いてた~

    2008年11月21日 15:24
    モデレータ
  •  さと581402 さんからの引用

    ファイルをデータベースに保存する際、GetLastWriteTimeでそのファイルの最終更新日を記録し、

    ファイルをデータベースから取り出す際にその更新日を付加してファイル出力したいのですが方法がよく分かりません。

     

    ファイル出力の際、下記構文で出力しております。

      If objRs.Read() Then
                Response.ContentType = CType(objRs.Item(0), String)
                Response.BinaryWrite(CType(objRs.Item(1), Byte()))
                Response.AddHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(objRs.Item(2)))
      End If

    objDb.Close()

    Response.End()

     

    この処理の後に、LastWriteTimeでファイルに更新日を設定するのだと思うのですが、どのように指定すれば

    いいのでしょうか?

     

    みなさんのレスから、結論としては、

     

    データベースから取り出されたバイト列データ objRs.Item(1) からファイルを
    作って、

     

    > 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものを

     

    > zipやlhaで圧縮し、

     

    その圧縮ファイルをバイト列データに変換し、Response.BinaryWrite メソッド
    で HTTP 出力ストリームに書き込み、

     

    > クライアント側でダウンロード後、それを展開

     

    ということになるようです。

     

    上記でよろしいでしょうか? > 回答者のみなさん

    2008年11月22日 4:39
  •  SurferOnWww さんからの引用

    上記でよろしいでしょうか? > 回答者のみなさん

     

    RFC2183の通りに記述してもそうならないのが気になります・・・。なんでろう? ちなみにこれはIEのみの現象ではありませんでした。もうちょっとトライしてみようかな・・・

    2008年11月23日 5:34
    モデレータ
  •  trapemiya さんからの引用

    RFC2183の通りに記述してもそうならないのが気になります・・・。なんでろう? ちなみにこれはIEのみの現象ではありませんでした。もうちょっとトライしてみようかな・・・

     

    RFC 2183 の 3. Examples を見ますと、ファイルの更新日を modification-date
    に設定するかどうかを選択するのは受信者であり、ブラウザが勝手に変えてしま
    ってはいけないということのように思えます。

     

    The recipient's user might also choose to set the last-modified date of
    the stored file to date in the modification-date parameter:

     

    2008年11月23日 8:36
  • 皆さま、ご回答ありがとうございます。

    さとと申します。

     

    ヘッダで更新日を指定することが無理なようなので、

     

    1)データベースから取り出されたバイト列データ objRs.Item(1) からサーバ上にファイルを作成。

    2)更新日時を変更。

    3)GZipStreamでzipに圧縮。

    4)Response.WriteFileでファイルをダウンロード。

     

    してみました。

     

    でも、「3)GZipStreamでzipに圧縮。」した際に、圧縮前のファイル更新日が勝手に変更されてしまいます。
    GZipStreamとはそういう物なのでしょうか?

    (解凍ソフトは「eo」を使っていますが、手動で圧縮したファイルは更新日が保持された形で解凍されるので

    解凍ソフトの問題ではないようです。)

     

     

    2008年11月27日 10:35
  •  さと581402 さんからの引用

    でも、「3)GZipStreamでzipに圧縮。」した際に、圧縮前のファイル更新日が勝手に変更されてしまいます。
    GZipStreamとはそういう物なのでしょうか?

     

    どうも、少なくともデフォルトでは、そういうもののようです。

     

    Msdn ライブラリの GZipStream クラスにあるサンプルプログラムで、

     

    FileStream outfile = File.Create("decommpressed.doc");
    outfile.Write(decompressedBuffer, 0, totalCount);

     

    を追加して、decommpressed.doc の更新日を見ると、確かに書き換えられて

    いました。

     

    何かの設定で変更しないようにすることができるかどうかまでは調べ切れていま

    せんが。

    2008年11月27日 15:06
  •  さと581402 さんからの引用

    でも、「3)GZipStreamでzipに圧縮。」した際に、圧縮前のファイル更新日が勝手に変更されてしまいます。

     

    今頃になって気がつきました。(汗)

     

    たぶん、FileStream で読んでくる実データのみを圧縮して送ることを考
    えていると思いますが、そもそも実データにはファイル名や更新日などの
    情報(メタデータ)は入ってないです。

     

    WinZip 等が作る zip アーカイブには、実データに加えてメタデータが含
    まれており、解凍時にメタデータを使ってファイル名や更新日時を設定し
    ているようです。

     

    という訳で、「圧縮前のファイル更新日が勝手に変更」と言うことではな
    さそうです。

     

    今回の目的を果たすには、実データに加えてメタデータも一緒に、世間一
    般に使われている解凍ツールと互換性のある zip アーカイブにして送っ
    てやる必要があるということになります。

     

    zip アーカイブを作るには、以下のサイトで紹介されている方法が役に
    立ちそうです。

     

    荒井省三のBlog: Dynamic Language SDK を使った ZIPアーカイブの使い方
    http://blogs.msdn.com/shozoa/archive/2008/09/24/how-to-zip-archive-by-using-dynamic-language-sdk.aspx

     

    例えば、ここで紹介されている「フリーのライブラリを使用する(たとえ
    ば、ここなど)。」のリンク↓

     

    The Zip, GZip, BZip2 and Tar Implementation For .NET
    http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx

     

    このライブラリを使えば、更新日時は自由に設定できますし、作った zip
    ファイルは WinZip で開けることは自分も確認済みです。圧縮するだけな
    らかなり簡単に出来ます(他の手段でも簡単かもしれませんが)。

     

    マイクロソフトのサンプルもありますが(下記サイトから入手できる)、
    これで作った圧縮ファイルは、WinZip と互換性がないです。理由は調べ
    てません(調べる前に諦めました)。

     

    Microsoft .NET Framework SDK version 2.0 Samples Download
    http://www.microsoft.com/downloads/details.aspx?FamilyID=adef80f9-1e44-4b94-be24-dff48f826ce6&DisplayLang=en

    2008年11月28日 12:30
  •  SurferOnWww さんからの引用

    みなさんのレスから、結論としては、

     

    データベースから取り出されたバイト列データ objRs.Item(1) からファイルを
    作って、

     

    > 一度サーバ上のどこかにファイルを書き込んで、更新日時を変更したものを

     

    > zipやlhaで圧縮し、

     

    その圧縮ファイルをバイト列データに変換し、Response.BinaryWrite メソッド
    で HTTP 出力ストリームに書き込み、

     

    > クライアント側でダウンロード後、それを展開

     

    ということになるようです。

     

    よく考えてみると、「一度サーバ上のどこかにファイルを書き込んで、更
    新日時を変更」というステップは不要でした。

     

    以下のステップで可能です。

     

    (1) データベースからバイト列データを取り出す。

     

    (2) 既存のライブラリを利用して zip アーカイブをバイト列として作成。
      更新日時やファイル名はその時設定。

     

    (3) 作成したバイト列を Response.BinaryWrite メソッドで HTTP 出力ス
      トリームに書き込み

     

    ご参考までに、先のレスで紹介した下記のサイトから入手できるライブラ
    リを使った例をアップしておきます。

     

    The Zip, GZip, BZip2 and Tar Implementation For .NET
    http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx

     

    実行するには Bin フォルダに ICSharpCode.SharpZipLib.dll を入れてお
    く必要があります(上記のサイトから入手できます)。

     

    Code Snippet

    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Data.SqlClient" %>
    <%@ Import Namespace="System.Configuration" %>
    <%@ Import Namespace="System.IO" %>
    <%@ Import Namespace="ICSharpCode.SharpZipLib.Zip" %>

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <script runat="server">

        protected void Page_Load(object sender, EventArgs e)
        {
            string connString =
                ConfigurationManager.ConnectionStrings["databaseConnectionString"].ConnectionString;
            SqlConnection connection = new SqlConnection(connString);
            string query = "SELECT filename, data FROM files WHERE id=@id";
            SqlCommand command = new SqlCommand(query, connection);
            command.Parameters.AddWithValue("@id", Convert.ToInt32(Request.QueryString["id"]));
            string filename = null;
            byte[] data = null;
           
            try
            {
                connection.Open();
                SqlDataReader reader = command.ExecuteReader();

                if (reader.Read())
                {
                    filename = (string)reader[0];
                    data = (byte[])reader[1];
                }
            }
            finally
            {
                connection.Close();
            }

            if (filename == null || data == null)
            {
                // DB から取得できなかった場合の処置(ここでは単に return)
                return;
            }

            Response.AppendHeader("Content-Disposition",
                "attachment; filename=" + HttpUtility.UrlEncode(filename) + ".zip");
            Response.ContentType = "application/x-zip-compressed";

            byte[] zippedData = new byte[data.Length];  // 圧縮前 (data.Length) よりは小さくなるはず。
            int zippedDataLength = 0;
            using (MemoryStream memoryStream = new MemoryStream(zippedData))
            {
                using (ZipOutputStream zipOutStream = new ZipOutputStream(memoryStream))
                {
                    zipOutStream.SetLevel(9); // 圧縮度の設定。9 が最高
                    ZipEntry entry = new ZipEntry(filename);
                    entry.DateTime = new DateTime(2000, 1, 1);  // ここで更新日時を設定
                    zipOutStream.PutNextEntry(entry);
                    zipOutStream.Write(data, 0, data.Length);               
                    zipOutStream.Finish();

                    // 圧縮後のサイズを取得。Finish() の前に置くのはダメ。zipOutStream.Length はダメ。
                    zippedDataLength = (int)zipOutStream.Position; 
                    zipOutStream.Close();
                }
            }       
            Array.Resize(ref zippedData, zippedDataLength);
            Response.BinaryWrite(zippedData);
            Response.End();
        }
    </script>

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title></title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server"></asp:Label>
        </div>
        </form>
    </body>
    </html>

     

     

    2008年11月29日 9:45
  • こんにちは。中川俊輔 です。

     

    皆様、多くの回答ありがとうございます。

     

    さとさん、フォーラムのご利用ありがとうございます。

    その後いかがでしょうか?

    有用な情報と思われる回答へ回答済みチェックをつけさせていただきました。

    追加の質問等ありましたら、ぜひ投稿してみてください。

     

    今後ともフォーラムをよろしくお願いします。

    それでは!

    2008年12月4日 6:18
  •  

    SurferOnWww 様

     

    お世話になっております。

    さとと申します。

     

    皆様からいろいろな情報をお教え頂き、テストを行っていたので、ご連絡が遅くなってしまいました。

     

    SurferOnWww 様からお教え頂いた「The Zip, GZip, BZip2 and Tar Implementation For .NET」の方法で実現しました。

     

    何でか、解凍ファイルが異常に大きくなってしまう現象が発生したので、ネット上でいろいろ調査した結果、

    「ICSharpCode.SharpZipLib.dll」のバージョンを0.85.5.452から0.84.0.0に下げたら正常に動作することができました。

     

    ありがとうございました。

    2008年12月8日 5:40
  •  さと581402 さんからの引用

    何でか、解凍ファイルが異常に大きくなってしまう現象が発生したので、ネット上でいろいろ調査した結果、

    「ICSharpCode.SharpZipLib.dll」のバージョンを0.85.5.452から0.84.0.0に下げたら正常に動作することができました。

     

    何故でしょうね。回答に使うツールとの相性でしょうか。

     

    自分は Ver. 0.85.5.452 で圧縮して、WinZip で解凍したのですが、圧縮前と

    解凍後のサイズは同じでした。

     

    別のツールでも調べて見ます。

     

     

    2008年12月8日 11:44