Download functionality doesnt work in IIS7

Apr 6, 2010 at 6:20 AM

Hi Everyone,

                  I have used below code to zip and  download files   which works perfectly in IIS and IIS6 but fails to work in IIS7. A window will open and blank out. Please anyone could help me out with this.Below is my code.Thanks in advance...    

                HttpContext.Current.Response.Clear();
                string archiveName = String.Format("Records-{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
                HttpContext.Current.Response.ContentType = "application/zip";
                HttpContext.Current.Response.AddHeader("content-disposition", "filename=" + archiveName);
                //Query
                using (ZipFile zip = new ZipFile())
                {
                   string tempDirectory = "c:\\Files";
                    DirectoryInfo di = new DirectoryInfo(tempDirectory);
                    FileInfo[] rgFiles = di.GetFiles();
                    foreach (FileInfo fi in rgFiles)
                    {
                        zip.AddFile(fi.FullName, "Records");
                    }
                    zip.Save(HttpContext.Current.Response.OutputStream);
                }
                HttpContext.Current.Response.End();

 

Regards,

Shamveel.

 

Coordinator
Apr 6, 2010 at 1:29 PM

Shamveel, try to use RequestComplete in place of Response.End().  Something like this:

System.Web.HttpContext c= System.Web.HttpContext.Current;
c.Response.Clear();
c.Response.BufferOutput= false;
string archiveName= String.Format("archive-{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
c.Response.ContentType = "application/zip";
c.Response.AddHeader("content-disposition", "inline; filename=\"" + archiveName + "\"");

using (ZipFile zip = new ZipFile())
{
    string tempDirectory = "c:\\Files";
    DirectoryInfo di = new DirectoryInfo(tempDirectory);
    FileInfo[] rgFiles = di.GetFiles();
    foreach (FileInfo fi in rgFiles)
    {
        zip.AddFile(fi.FullName, "Records");
    }
    zip.Save(c.Response.OutputStream);
}
c.ApplicationInstance.CompleteRequest();

 

Apr 6, 2010 at 3:02 PM

Hi Cheeso..

               Thank you for your reply. I will try the method mentioned by you.Forgot to mentioned that the download functionality working fine in Mozilla. In IE browser doesn't work.

 

Regards

Shamveel.

Apr 6, 2010 at 3:26 PM

Hi Cheeso,

              No luck... :( . I couldn't understand this behavior...

 

Apr 6, 2010 at 3:36 PM

Hey cheeso,

                 I got a chance to test the same in the server ( i mean locally..ex"http://localhost/app/ ) .The functionality works fine ther.. If i try to do the same from my machine it doesnt work ( IE browser)

 

Coordinator
Apr 6, 2010 at 3:47 PM

If that's true, then it could be a matter of caching.  Try inserting a Response.Flush() before the call to CompleteRequest().

 

Apr 6, 2010 at 6:45 PM

Its not working cheeso. I feel like some thing we need to do in  " zip.Save(c.Response.OutputStream); " were the file will be given as output. I couldnt understand where to do wat.Just wondering how does it works in Mozilla..? 

Coordinator
Apr 6, 2010 at 7:26 PM

> .Just wondering how does it works in Mozilla..?

That's what I mean by, it could be a matter of caching.

If I were debugging this, I would look at the returned bytestream, via Fiddler or some other trace tool.

 

Apr 6, 2010 at 7:32 PM

Sure cheeso, i will do whatever you want me to.Will get back to you  by tomorrow with the fiddler output.. Thanks..

 

Apr 7, 2010 at 8:12 AM

Hey Cheeso,

Below is the output what i recieved from fiddler:

                 IIS6: Which works fine

 

HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 565055
Content-Type: application/zip
Server: Microsoft-IIS/6.0
MicrosoftSharePointTeamServices: 6.0.2.5530
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
content-disposition: filename=Records-2010-Apr-07-120740.zip
Date: Wed, 07 Apr 2010 06:37:40 GMT
Connection: close

 

IIS7:(In our server which works fine )

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/zip
Server: Microsoft-IIS/7.0
content-disposition: filename=Records-2010-Apr-07-122616.zip
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Wed, 07 Apr 2010 06:56:15 GMT
Content-Length: 405526

IIS7:(In hosting server where doesnt work)

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/zip
Server: Microsoft-IIS/7.0
content-disposition: filename=Records-2010-Apr-07-123202.zip
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Wed, 07 Apr 2010 07:02:02 GMT
Content-Length: 3201039

 

Let me know if you need more information..  Thanx..

 

Coordinator
Apr 7, 2010 at 8:34 PM

Mmm, yes, so the headers are virtually identical.

One question:  why are the content-length values so different? Did you zip the same file each time?  In that case, there's a cause for concern, and evidence of a difference.  It doesn't explain the difference, but it  makes it pretty clear.  On the other hand, maybe you zipped different files in each case.  If that were true, then the differing content-length would be expected.

Beyond on the headers, I'm really more interested in the data that follows.  Did you get all the data, in each case?   Does Fiddler indicate that all of the data arrived?

It may be easier to troubleshoot this if you reduce the size of the zip that is generated. on the other hand that may also cause the problem to disappear.

 

Coordinator
Apr 7, 2010 at 9:16 PM
Edited Apr 7, 2010 at 9:19 PM

Another thing -

have you set the buffering off, and cleared the headers before beginning the transfer? IT should look something like this:

    c.Response.Clear();
    c.Response.ClearHeaders();
    c.Response.BufferOutput= false;

This should appear before writing anything to the response stream.

Here's the thing - the HTTP protocol provides a mechanism by which a server can tell a client (browser) how much data is coming. This is the Content-Length header.  This is known for small transfers, let's say an HTML page that is generated from ASP.NET , and is about 8k in length.  The way it works is, the ASPNET runtime caches the response, and determines the size of it, before sending any of the response to the requesting client.  For large responses, like a binary file, or a dynamically-generated zip file, the ASPNET runtime cannot possibly cache all that data.  So the size of the data is not known, at the time the first few bytes are sent, which means ASPNET cannot respond with a Content-Length header.

The HTTP specification allows for this, using what's called "chunked" Transfer-Encoding. Instead of caching the response, determining the size, and injecting a "Content-Length" header into the response, before sending it in its entirety, with chunked encoding, ASPNET injects a header like "Transfer-Encoding: Chunked" , and then begins transmitting the data.  The data arrives in chunks, each chunk marked with headers.  The final chunk is marked specially.  The client stops downloading after receiving this specially-marked chunk.  This is all documented in the HTTP spec. 

ASP.NET handles the chunking for you automatically, when using chunked encoding.  So the question is, how to turn on chunked encoding?  With other headers you can simply call Response.AddHeader("transfer-encoding", "chunked");   But this is not permitted by ASPNET, for that header.  So you have to do it implicitly.  Setting the buffering to false should do it.  It should also work to call Flush() on the ResponseStream, at any point after having written something to the Response stream, and before the final close of the stream.  That really isn't possible when saving a file to the stream, as is the case in dynamically generating a zip file with DotNetZip, so you'll have to use the BufferOutput=false; thing. The resulting response headers should look like this:

HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/zip
Server: Microsoft-IIS/7.0
content-disposition: inline; filename="archive-2010-Apr-07-160954.zip"
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Wed, 07 Apr 2010 20:09:54 GMT

 

Apr 12, 2010 at 8:43 AM

Hey Cheeso,

                     Sorry for the late reply as i was busy with my other schedule. The content length difference is mainly becoz of the number of files ; if you go by one file also application wont pop up for download. I have used the above method mentioned by you still its the same.Here is the fiddler output.                

HTTP/1.1 200 OK
Cache-Control: private
Transfer-Encoding: chunked
Content-Type: application/zip
Server: Microsoft-IIS/7.0
content-disposition: inline; filename="Records-2010-Apr-12-130825.zip"
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Mon, 12 Apr 2010 07:38:25 GMT

And i wanted to know that why it acts differently in two machines ( i mean when i used in our local server-IIS7 it works fine ,only in hosting server this is the issue-that too only when we access it through IE)

Thanx...

 

Coordinator
Apr 12, 2010 at 3:44 PM
shamveel wrote:

And i wanted to know that why it acts differently in two machines ( i mean when i used in our local server-IIS7 it works fine ,only in hosting server this is the issue-that too only when we access it through IE)

Yes, I have a theory that the difference you're seeing is because of a problem with the caching.  This is why I said that the Fiddler information would be interesting. Once again, it's not only the headers that are the interesting part.  You should also be interested in the actual length of content that is returned, for the case that works properly, as well as for the case that doesn't work properly.

 

 

Jul 8, 2010 at 5:15 PM
Edited Jul 8, 2010 at 5:34 PM

Could this have anything to do with some of the native compression in IIS7 that is not turned on in IIS6.  I am attempting to configure IIS Compression on IIS6, and after I update the MetaBase.xml with the compression setting I can no longer get the zip files with work.  They will download from the site, but when you try and open the file it says the zip file is invalid.  If I remove the compression settings it works fine.  Any thoughts.  I might create a seperate thread just thought this sounded similiar.

http://dotnetzip.codeplex.com/Thread/View.aspx?ThreadId=218795