Frage

We have a web page that is grabs a series of strings from a url, finds some pdfs associated with those strings, zips them up using DotNetZip, and returns them to the user. The page that does this is very simple - here's the 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();
}

(Before you ask, it would be fine if someone put other values in this url...these are not secure files.)

This works fine on my development box. However, when testing on our QA system, it downloads the zipped file, but it is corrupt. No error is thrown, and nothing is logged in the event log.

It may be possible for me to find a way to interactively debug on the QA environment, but since nothing is actually failing by throwing an error (such as if the dll wasn't found, etc.), and it's successfully generating a non-empty (but corrupt) zip file, I'm thinking I'm not going to discover much by stepping through it.

Is it possible that this is some kind of issue where the web server is "helping" me by "fixing" the file in some way?

I looked at the http response headers where it was working on my local box and not working on the qa box, but while they were slightly different I didn't see any smoking gun.

As an other idea I rejected, the content length occured to me as a possibility since if the content length value was too small I guess that would make it corrupt...but I'm not clear why that would happen and I don't think that's exactly it since if I try to zip and download 1 file I get a small zip...while downloading several files gives me a much larger zip. So that, combined with the fact that no errors are being logged, makes me think that the zip utility is correctly finding and compressing files and the problem is elsewhere.

Here are the headers, to be complete.

The response header on my development machine (working)

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

The response header on the qa machine (not working)

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

Not sure how to approach this since nothing is claiming a failure. I feel like this could be a web server configuration issue (since I don't have any better ideas), but am not sure where to look. Is there a tact I can take?

War es hilfreich?

Lösung

As it is you have miss to give an End() to the page right after the Flush() as:

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

But this is not the correct way, to use a page to send a zip file, probably IIS also gZip the page and this may cause also issues. The correct way is to use a handler and also avoid extra gZip compression for that handler by ether configure the IIS, ether if you make the gZip compression avoid it for that one.

a handler with a name for example download.ashx for your case will be as:

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);
      }
    }  
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top