[
  {
    "Id": "151674",
    "ThreadId": "45459",
    "Html": "Can the following be done with DotNetZip?<br>\r\n<strong>Usage: </strong>Browser client receives a zip file [of known size] [possibly a self extractor zip file] from ASP.Net and starts downloading.&nbsp; <br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Server meanwhile is filling the zipOutStream with data.<br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; When done, user can save zipfile (or self extractor file). <br>\r\n<strong>Functionality: </strong><br>\r\na. Server adds &quot;filenames&quot; and file sizes to be added (including compression methods)<br>\r\nb. Server streams a zipfile header to Response.Output<br>\r\nc. In a buffer filling loop: <br>\r\n&nbsp;&nbsp; i. Server adds buffered input to input streams creating the &quot;files&quot;.<br>\r\n&nbsp;&nbsp; ii. Server streams the current information to Respone.Output<br>\r\nd. When done filling info: <br>\r\n&nbsp; i. Server streams the zip footer information<br>\r\n&nbsp; ii. Client when done receiving sees the &quot;Save / Open&quot; dialog.<br>\r\n<br>\r\nIf so, could you point to or give a code snippet.<br>\r\nIf not, would you wish for me to contribute? - And then your thoughts on design for this? <br>\r\n",
    "PostedDate": "2009-01-28T02:12:05.95-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "153423",
    "ThreadId": "45459",
    "Html": "There's an example that does what I think you want, <br>\r\nhere: <br>\r\n<a href=\"http://code.msdn.microsoft.com/DotNetZip\">http://code.msdn.microsoft.com/DotNetZip</a><br>\r\n",
    "PostedDate": "2009-02-02T11:19:51.837-08:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "206565",
    "ThreadId": "45459",
    "Html": "<p>Hi Cheeso, and thanks for your answer, but the example is no good.</p>\r\n<p>&nbsp;</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre>        <span style=\"color:Blue\">using</span> (ZipFile zip = <span style=\"color:Blue\">new</span> ZipFile())\r\n        {\r\n            <span style=\"color:Blue\">foreach</span> (var f <span style=\"color:Blue\">in</span> filesToInclude)\r\n            {\r\n                zip.AddFile(f, <span style=\"color:#A31515\">&quot;files&quot;</span>);\r\n            }\r\n            zip.AddFileFromString(<span style=\"color:#A31515\">&quot;Readme.txt&quot;</span>, <span style=\"color:#A31515\">&quot;&quot;</span>, ReadmeText);\r\n            zip.Save(Response.OutputStream);\r\n        }\r\n        Response.End();\r\n\r\nWhereas I need something like the following  (so that <strong>while</strong> I'm saving the zip, the user is already receiving it):<br>I can show you that this is what many of the posts where you advertised DotNetZip with the former code,  &nbsp; are actually requesting.<br>It can be done with ZipSharpLib but not with DotNetZip.<br></pre>\r\n</div>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre><span style=\"color:Blue\">    using</span> (ZipFile zip = <span style=\"color:Blue\">new</span> ZipFile()) \r\n    { \r\n    <span style=\"color:Blue\">    foreach</span> (var f <span style=\"color:Blue\">in</span> filesToInclude)\r\n        { \r\n            zip.AddFile(f, <span style=\"color:#A31515\">&quot;files&quot;</span>);\r\n            zip.WriteToOutput(Response.OutputStream); \r\n            Response.Flush(); \r\n        } \r\n        zip.AddFileFromString(<span style=\"color:#A31515\">&quot;Readme.txt&quot;</span>, <span style=\"color:#A31515\">&quot;&quot;</span>, ReadmeText);\r\n        zip.WriteToOutput(Response.OutputStream); \r\n        Response.Flush(); \r\n    } \r\n    Response.End(); \r\n    // In any case, thanks for the great tool!</pre>\r\n</div>\r\n<pre>     </pre>\r\n<p>&nbsp;</p>\r\n<p><img id=kosa-target-image style=\"visibility:hidden;z-index:2147483647;left:221px;top:19px\" alt=\"\"></p>",
    "PostedDate": "2009-06-29T05:49:10.53-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "206567",
    "ThreadId": "45459",
    "Html": "<p>Keywords for this question:<br>&nbsp; realtime zip,&nbsp; real time zip, <br>&nbsp; zip created on the fly, <br>&nbsp; immediate zip download, <br>&nbsp; streamed zip to output</p>\r\n<p><img id=kosa-target-image style=\"visibility:hidden;z-index:2147483647;left:141px;top:23px\" alt=\"\"></p>",
    "PostedDate": "2009-06-29T05:54:28.597-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "206661",
    "ThreadId": "45459",
    "Html": "<p>Yes, in fact you can do what you want, using what I have called the <em>just-in-time stream provisioning mechanism </em>in v1.8 of DotNetZip.&nbsp;</p>\r\n<p>Although, I would suggest that you be careful&nbsp;about insisting that the browser &quot;must receive the file as the server sends it&quot;.&nbsp; [<span style=\"color:Maroon\"><em>EDIT</em>: Of course you want the browser to receive the file as soon as the server sends it - this is what streaming is.&nbsp;&nbsp; And as I've told you, and as I have explained in other places that you seem to have read, DotNetZip uses a streaming approach.&nbsp;&nbsp; By saying the browser &quot;must receive the file as soon as the server sends it,&quot;&nbsp; I think you are really implying &quot;the browser must receive the file as soon as my app calls AddFile().&quot;&nbsp;&nbsp; I think you are concluding, incorrectly and without justification, that the&nbsp;compression is happening at the time of the call to AddFile.&nbsp;]</span>&nbsp;&nbsp; It seems like an implementation detail that typically, you would not need to concern yourself with.&nbsp; Is it&nbsp;performance that concerns you?&nbsp; Which aspect?&nbsp; Time-to-first-byte?&nbsp; Time-to-last-byte?&nbsp;&nbsp;Something else?&nbsp;&nbsp; If performance is your concern, I suggest that you benchmark the easy approach with DotNetZip, before dismissing it as not appropriate or &quot;no good&quot;. &nbsp; It actually *does* stream the zip file to the browser.&nbsp;</p>\r\n<p>On the other hand I can see situations involving dynamically-created input streams, where the JIT stream provisioning would be ideal.&nbsp; There <em>may</em> also be some benefit when the&nbsp;zip file is huge, with tens of thousands of entries.&nbsp; But these are not mainstream scenarios.</p>\r\n<p>You offered to contribute something, and I appreciate the offer.&nbsp; But before we go forward, I need to better understand the problem we're trying to solve here.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-06-29T09:24:49.227-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208014",
    "ThreadId": "45459",
    "Html": "<p>I need zip exactly for this reason, I'm putting together a group of very large files, &nbsp;some of them media files, others part of an application (without compression).</p>\r\n<p>Call this performance, or call it common sense: <br>a. Why should the user wait the whole time it takes to create this zipfile in memory, and only then start downloading it?<br>b. Why should the server's memory have a full copy of this giant file aggragation, when it could be simply streaming it off, a chunk at a time?</p>\r\n<p>How do I use the JIT stream provisioning mechanism?&nbsp; Is it documented?</p>\r\n<p>My offer to contribute is thus: (I didn't see you source code yet): <br>Add four methods:&nbsp;<strong>WriteEntry(OutputStream out, ZipEntry entry)</strong>,&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>WriteHeader/Footer(OutputStream out, List&lt;string&gt; files);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong>and <strong>CalculateZipfileSize(OutputStream out, List&lt;string&gt; files);)</strong>&nbsp;<br>These methods replace the &quot;Save&quot;, which do the following: <br>a. Throw exception if the method of compression is not STORE (ie UNCOMPRESSED) for all files.<br>b. Calculates the size of the zipfile, according to the files which will be stored in it<br>c. Writes an entry to&nbsp;an output (or stream). <br>d. Writes the zip header or zip footer&nbsp;</p>\r\n<p>Moshe</p>",
    "PostedDate": "2009-07-02T09:10:27.76-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208019",
    "ThreadId": "45459",
    "Html": "<p>Or maybe instead of <strong>WriteEntry&nbsp;&nbsp;</strong>have <strong>Write(OutputStream out, Array buffer)<br></strong>and I would have low level control on what is currently in the buffer...<br>so I could send chunks of information say 100K at a time.</p>",
    "PostedDate": "2009-07-02T09:14:51.73-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208077",
    "ThreadId": "45459",
    "Html": "<p>Thanks for your suggestions. I think you have a basic misconception about how the DotNetZip library works.</p>\r\n<p>When you call&nbsp;zip.AddFile(foo...) , the call stores metadata about the entry you have added.&nbsp;&nbsp; It does not produce a zip file in memory at that time.&nbsp; It stores information about the entry that will eventually be part of the zipfile.&nbsp;</p>\r\n<p>What information?&nbsp; Things like: the filename, the timestamp on the file, and whether encryption and compression should be used when the file is eventally put into the Zip archive.&nbsp; No compression or encryption is performed at the time of the call to AddFile() or&nbsp;AddEntry() and their cousins. These operations (AddFile etc)&nbsp;are generally very fast, because they only collect and store metadata.</p>\r\n<p>It is when you call Save() that the zipfile is then constructed, using the metadata stored in memory.&nbsp; The compression and encryption is performed at that time.&nbsp; If you call Save() and pass a stream, DotNetZip writes the zip content directly to the output stream.&nbsp; Because it uses a stream approach, the application never has &quot;a full copy of this giant file aggregation&quot; in memory as you put it.&nbsp; I appreciate your concern about that, because it would be silly to create the entire zip file in memory.&nbsp; But it does not happen.</p>\r\n<p>When you call Save() the possibly compressed, possibly encrypted content is sent to the stream, which does whatever it wants with it.&nbsp; &nbsp;In particular, if you call ZipFile.Save(), passing Response.OutputStream as the stream, then DotNetZip will put the zipfile bytes directly into the Response.OutputStream, <em>as they are constructed</em>, and the browser is able to immediately begin downloading the bytes while the compression is happening.&nbsp; Obviously this can and does happen before the zipfile is fully constructed.&nbsp;&nbsp;In the general case the browser will be dowloading bytes for an entry within the zipfile before even that particular entry is fully compressed.&nbsp;</p>\r\n<p>In no case is there &quot;a giant file aggregation&quot; stored in memory on the server.&nbsp; Ever.&nbsp; The only time you will have a giant aggregation in memory is if you call Save() to a MemoryStream(), which by definition stores data into memory.&nbsp; If you for example call Save() with a filename, then the zipped data is <em>streamed </em>to the file, in a manner similar to the streaming to the browser.&nbsp; Here again, there is no &quot;giant aggregation.&quot;&nbsp;</p>\r\n<p>All of this is documented in the helpfile.&nbsp; <a href=\"http://cheeso.members.winisp.net/DotNetZipHelp\">http://cheeso.members.winisp.net/DotNetZipHelp</a>&nbsp; The JIT streaming mechanism is also fully documented and explained, although now it sounds like you don't need it. &nbsp;</p>\r\n<p>Regarding CalculateZipfileSize(), that's an interesting idea, and I can see the utility in it.&nbsp; But getting the size is not possible, without actually performing the compression and encryption.&nbsp; There's no way to predict, a-priori, how well a particular data stream will compress.&nbsp; Because you don't know the size until you actually do the compression, you cannot know the size of the zip file until it is created.&nbsp;</p>\r\n<p>Your efforts to improve DotNetZip are admirable, but I suggest before you devote any more time to improving it, you first spend some time better understanding how it works.</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-07-02T11:26:02.13-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208083",
    "ThreadId": "45459",
    "Html": "<p>ps: regarding your desire to manage the chunks that get sent -&nbsp; see the BufferSize property on the ZipFile.&nbsp;</p>\r\n<p>However, keep in mind that the stream is very fast, and there are multiple levels of buffering between a typical webserver and browser.&nbsp; As a result there is no guarantee that there will be a discrete &quot;one chunk at a time&quot; behavior.&nbsp;&nbsp; The chunk size on the client (browser) will not be the same size as the chunksize on the server.&nbsp; The BufferSize property allows you to balance memory size versus compression overhead.&nbsp; For many small files, a smaller buffer is warranted.&nbsp; If you have large files, a buffersize of 1mb might be better.&nbsp; There are no hard and fast rules, you'll have to test it.&nbsp;</p>\r\n<p>And yes, ZipFile.BufferSize is documented, too.</p>\r\n<p><a href=\"http://cheeso.members.winisp.net/DotNetZipHelp\">http://cheeso.members.winisp.net/DotNetZipHelp</a></p>",
    "PostedDate": "2009-07-02T11:39:30.587-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208640",
    "ThreadId": "45459",
    "Html": "<p>Wow! OK!&nbsp; So if I understand correctly, DotNetZip will do real-time streaming on the fly, by simply saving to OutputStream when done defining, <br>and no &quot;write()&quot; needs to be done during definition, since no processing is done at that stage anyway.</p>\r\n<p>I'll check to see if it works OK for me, (and starts streaming immediately) and if so will also correct various forums (about sharpZip)<br>where I followed up on your entry,(I had&nbsp;written to say that&nbsp;your library seemed&nbsp;not to stream on the fly)</p>\r\n<p>&nbsp;</p>\r\n<p>Thanks! Moshe</p>",
    "PostedDate": "2009-07-05T00:40:26.383-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208664",
    "ThreadId": "45459",
    "Html": "<p>DotNetZip 1.8 - When trying it with small files, it works fine (seemingly).</p>\r\n<p>When replacing the same files with large ones (same filenames so everything is OK &quot;pathwise&quot;), <br>in IE8 I do not get the &quot;Download file&quot; dialog, but rather I wait a while, with the IE progress bar advancing and it says the page is downloading, <br>and then finally it stops and I get: Internet Explorer cannot display the webpage. - Obviously a timeout.</p>\r\n<p>How can I cause it to give me the &quot;download file&quot; dialog first, and <strong>only then </strong>continue streaming while creating the output?</p>\r\n<p>BTW the Calculate() is useful for ForceNoCompression - but that usage IS VERY common.</p>\r\n<p>Thanks again, and will get my company to contribute ...</p>\r\n<p>Moshe</p>",
    "PostedDate": "2009-07-05T05:29:12.323-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208671",
    "ThreadId": "45459",
    "Html": "<p>I'd have to see your server-side code to give you any insight into why zipping large files doesn't work with IE8.&nbsp; Normally what you describe - getting the download file dialog first - is how it happens.&nbsp; Have you tried on IE7 or Firefox?</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-07-05T06:45:38.66-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208861",
    "ThreadId": "45459",
    "Html": "<p>Thanks for the speedy response!!!<br>Firefox fails in the same way.&nbsp; Please see remarks at the bottom of this posting.<br>The server side code is:</p>\r\n<div style=\"color:Black;background-color:White\">\r\n<pre> <span style=\"color:Blue\">protected</span> <span style=\"color:Blue\">void</span> Page_Load(<span style=\"color:Blue\">object</span> sender, EventArgs e)\r\n {\r\n            tryDotNetZip(<span style=\"color:Blue\">new</span> ArrayList(){<span style=\"color:#A31515\">&quot;ErrorPage.htm&quot;</span>, <span style=\"color:#A31515\">&quot;temp1.tmp&quot;</span>, <span style=\"color:#A31515\">&quot;temp2.tmp&quot;</span>, <span style=\"color:#A31515\">&quot;ErrHandler.cs&quot;</span>});\r\n }\r\n\r\n\r\n <span style=\"color:Blue\">private</span> <span style=\"color:Blue\">void</span> tryDotNetZip(ArrayList filesToInclude)\r\n {\r\n                Response.Clear();\r\n                <span style=\"color:Blue\">string</span> zipName = String.Format(<span style=\"color:#A31515\">&quot;archive-{0}.zip&quot;</span>, DateTime.Now.ToString(<span style=\"color:#A31515\">&quot;yyyy-MMM-dd-HHmmss&quot;</span>));\r\n                <span style=\"color:Green\">//const string zipName = &quot;moshe.zip&quot;;</span>\r\n                Response.ContentType = <span style=\"color:#A31515\">&quot;application/zip&quot;</span>;\r\n                Response.AddHeader(<span style=\"color:#A31515\">&quot;content-disposition&quot;</span>, <span style=\"color:#A31515\">&quot;filename=&quot;</span> + zipName);\r\n                <span style=\"color:Green\">//Response.Flush();</span>\r\n                <span style=\"color:Blue\">using</span> (ZipFile zip = <span style=\"color:Blue\">new</span> ZipFile())\r\n                {\r\n                    <span style=\"color:Green\">//zip.BufferSize = 2000;</span>\r\n                    zip.ForceNoCompression = <span style=\"color:Blue\">true</span>;\r\n\r\n                    <span style=\"color:Blue\">foreach</span> (<span style=\"color:Blue\">string</span> f <span style=\"color:Blue\">in</span> filesToInclude)\r\n                    {\r\n                        <span style=\"color:Blue\">string</span> filename = Path.Combine(Server.MapPath(<span style=\"color:#A31515\">&quot;.&quot;</span>), f);\r\n                        zip.AddFile(filename, <span style=\"color:#A31515\">&quot;files&quot;</span>);\r\n                    }\r\n                    zip.Save(Response.OutputStream);\r\n                    <span style=\"color:Green\">//Response.Flush();</span>\r\n                }\r\n            Response.End();\r\n        }\r\n\r\n</pre>\r\n</div>\r\n<p>_________________________<br>Please note that all files exist, and that the files temp1.tmp and temp2.tmp are replaced from small text files (with a rapid and successful zip) to large zipfiles, <br>using a simple &quot;rename&quot; call in DOS.<br>I also tried changing the names in the ArrayList of the called files to &quot;temp1Big.tmp, temp2Big.tmp&quot;&nbsp; (with respective files in the directory) but to no avail.<br><br>Thanks again, and hope you enjoyed the holiday weekend <br>(I'm&nbsp;on the other side of the atalantic, reason for the strange hours),<br>Moshe</p>",
    "PostedDate": "2009-07-06T02:39:28.263-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208870",
    "ThreadId": "45459",
    "Html": "<p>Tried content type application/octet-Sream: <strong>Did not help.</strong><br>(In SharpZipLib when buffering, I got a &quot;corrupt zip file&quot;, if I used Application/Zip, and only changing to octet helped me...)<br><br>Also tried adding the Response.Flush(); after the header setting (and before using zip). <strong>Did not help </strong>either.<br><br>Thanks, Moshe</p>",
    "PostedDate": "2009-07-06T03:07:17.847-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208873",
    "ThreadId": "45459",
    "Html": "<p>(I don't know how to edit an entry here, so posting another one with a correction)</p>\r\n<p>I meant to say:</p>\r\n<p>Please note that all files exist, and that the files temp1.tmp and temp2.tmp are replaced from small text files (<strong>which result in&nbsp;</strong>a rapid and successful zip<strong>file output</strong>) <br>to <strong>renamed </strong>large zipfiles, using a simple &quot;rename&quot; call in DOS.&nbsp; <strong>So now, temp1.tmp and temp2.tmp are very large files (247 MB each)</strong><br>I also tried changing the names in the ArrayList of the called files to &quot;temp1Big.tmp, temp2Big.tmp&quot;&nbsp; (with respective files in the directory) but to no avail.<br></p>",
    "PostedDate": "2009-07-06T03:15:45.887-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "208975",
    "ThreadId": "45459",
    "Html": "<p>I read a little more about HTTP and streamed transfer, in <a href=\"http://www.ietf.org/rfc/rfc2616.txt\">RFC 2616</a>, and also in the <a href=\"http://msdn.microsoft.com/en-us/library/system.web.httpresponse.bufferoutput.aspx\">doc for HttpResponse</a>.&nbsp; What I learned was that in ASP.NET&nbsp;the http response is, by default, buffered.&nbsp;&nbsp; If you turn off buffering, you should get a chunked transfer-encoding, which means it will send data as soon as it is written in the server.&nbsp; Use this:</p>\r\n<pre>        Response.BufferOutput= false;  \r\n</pre>\r\n<p>..directly after Response.Clear() to turn off buffering.</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2009-07-06T08:26:40.66-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "210200",
    "ThreadId": "45459",
    "Html": "<p>Works!!!&nbsp; Thanks!!!!!</p>\r\n<p>Moshe</p>",
    "PostedDate": "2009-07-08T16:16:26.407-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "210220",
    "ThreadId": "45459",
    "Html": "<p>Glad it helped!</p>",
    "PostedDate": "2009-07-08T17:27:45.833-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  }
]