1

URL から一連の文字列を取得し、それらの文字列に関連付けられているいくつかの pdf を見つけ、それらをDotNetZipを使用して圧縮し、ユーザーに返す Web ページがあります。これを行うページは非常に単純です。これが Page_Load です。

protected void Page_Load(object sender, EventArgs e)
{
    string[] fileNames = Request.QueryString["requests"].Split(',');
    Response.Clear();
    Response.ClearHeaders();
    Response.ContentType = "application/zip";
    string archiveName = String.Format("MsdsRequest-{0}.zip", DateTime.Now.ToString("yyyy-mm-dd-HHmmss"));
    Response.AddHeader("Content-Disposition", "attachment; filename=\"" + archiveName + "\"");

    using (ZipFile zip = new ZipFile())
    {
        foreach (string fileName in fileNames)
        {
            zip.AddFile(String.Format(SiteSettings.PdfPath + "{0}.pdf", msdsFileName), "");
        }
        zip.Save(Response.OutputStream);
    }
    Response.Flush();
}

(質問する前に、誰かがこの URL に他の値を入れても問題ありません...これらは安全なファイルではありません。)

これは私の開発ボックスでうまくいきます。ただし、QA システムでテストすると、圧縮されたファイルがダウンロードされますが、破損しています。エラーはスローされず、イベント ログには何も記録されません。

QA環境でインタラクティブにデバッグする方法を見つけることは可能かもしれませんが、エラーをスローして実際に失敗するものは何もないため(dllが見つからないなど)、非エラーを正常に生成しています.空の (しかし破損した) zip ファイルの場合、それを調べてもあまり発見できないと思います。

これは、何らかの方法でファイルを「修正」することにより、Web サーバーが私を「助けている」というある種の問題である可能性はありますか?

ローカル ボックスで動作し、qa ボックスでは動作していない http 応答ヘッダーを見ましたが、わずかに異なっていましたが、発煙弾は見当たりませんでした。

私が拒否した別のアイデアとして、コンテンツの長さの値が小さすぎると破損する可能性があるため、コンテンツの長さが可能性として思い浮かびました...しかし、なぜそれが起こるのかはっきりしていません。 1つのファイルを圧縮してダウンロードしようとすると、小さなzipが得られるため、まさにそれだと思います...複数のファイルをダウンロードすると、はるかに大きなzipが得られます。そのため、エラーがログに記録されていないという事実と相まって、zip ユーティリティがファイルを正しく見つけて圧縮しており、問題は別の場所にあると思います。

ヘッダーは次のとおりです。

私の開発マシンの応答ヘッダー(動作中)

HTTP/1.1 200 OK
Date: Wed, 02 Jan 2013 21:59:31 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Content-Disposition: attachment; filename="MsdsRequest-2013-59-02-165931.zip"
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: application/zip

qa マシンの応答ヘッダー (機能していません)

HTTP/1.1 200 OK
Date: Wed, 02 Jan 2013 21:54:37 GMT
Server: Microsoft-IIS/6.0
P3P: CP="NON DSP LAW CUR TAI HIS OUR LEG"
SVR: 06
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Content-Disposition: attachment; filename="MsdsRequest-2013-54-02-165437.zip"
Cache-Control: private
Content-Type: application/zip
Set-Cookie: (cookie junk removed);expires=Wed, 02-Jan-2013 21:56:37 GMT;path=/;httponly
Content-Length: 16969

失敗を主張するものは何もないため、これにアプローチする方法がわかりません。これは Web サーバーの構成の問題である可能性があると思いますが (より良いアイデアがないため)、どこを見ればよいかわかりません。私が取ることができるタクトはありますか?

4

1 に答える 1

1

そのままでは、ページのasEnd()の直後にto を指定するのを忘れています。Flush()

 ...
        zip.Save(Response.OutputStream);
    }
    Response.Flush();
    Response.End();
}

しかし、これはページを使用して zip ファイルを送信する正しい方法ではありません。おそらく IIS もページを gZip し、これも問題を引き起こす可能性があります。正しい方法は、ハンドラーを使用し、そのハンドラーの余分な gZip 圧縮を回避することです。これには、IIS を構成する必要があります。

download.ashxたとえば、ケースの名前を持つハンドラーは次のようになります。

public void ProcessRequest(HttpContext context)
    {
      string[] fileNames = Request.QueryString["requests"].Split(',');          
      context.Response.ContentType = "application/zip";          
      string archiveName = String.Format("MsdsRequest-{0}.zip", DateTime.Now.ToString("yyyy-mm-dd-HHmmss"));          
      context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + archiveName + "\"");

      // render direct
      context.Response.BufferOutput = false;

      using (ZipFile zip = new ZipFile())
      {
        foreach (string fileName in fileNames)
        {
            zip.AddFile(String.Format(SiteSettings.PdfPath + "{0}.pdf", msdsFileName), "");
        }
        zip.Save(context.Response.OutputStream);
      }
    }  
于 2013-01-02T23:43:54.417 に答える