[
  {
    "Id": "418929",
    "ThreadId": "205170",
    "Html": "<p>Hello, great software you have, very easy to use!&nbsp;</p>\r\n<p>I'm trying to figure out the best way to save my zipe file to SQL (VarBinary[MAX] col), I believe that's the best column type to use?</p>\r\n<p>So I'm reading the zipfile using a Filestream obj and then converting that into a byte array and saving to the DB.&nbsp;</p>\r\n<p>My problem is, I can read back from DB but don't know how to convert back into a Zipfile obj and save back out to file system. I tried to serialize the Zipfile class , but the exception I got was &quot;Not serializable&quot;.&nbsp;</p>\r\n<p>Any help would be greatly appreciated,</p>",
    "PostedDate": "2010-03-16T15:58:16.09-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  },
  {
    "Id": "419017",
    "ThreadId": "205170",
    "Html": "<p>Hello! and thanks for using the forum.</p>\r\n<p>First, I'm going to recommend that you use streams.&nbsp; Both SQL Server and DotNetZip support streams nicely.</p>\r\n<p>In SQL Server, it's possible to open a stream directly onto a BLOB (or VarBinary MAX), for reading or writing.&nbsp;&nbsp;&nbsp;With DotNetZip, you can save a ZipFile into any Stream object, and you can read a zip file from any stream.&nbsp; You can plug the two together fairly easily.&nbsp; There are some gotchas or limitations.</p>\r\n<h2>SQL 2008's FILESTREAM makes this easy</h2>\r\n<p>If you&nbsp;have SQL 2008, and you've enabled the FILESTREAM&nbsp;capability, the type you would use is the SqlFileStream.&nbsp; This works for reading or writing.&nbsp; <a href=\"http://msdn.microsoft.com/en-us/library/cc716724.aspx\">Microsoft has a nice article with&nbsp;examples</a>.</p>\r\n<p>Reading a zip file from SQL2008 is as simple as opening the SqlFileStream and instantiating a ZipFile type, passing that stream to the constructor.&nbsp; Saving a zip file into SQL2008 works similarly; just call the ZipFile.Save() method that accepts a stream, and pass the SqlFileStream.&nbsp; This will work nicely.&nbsp;</p>\r\n<h2>No FILESTREAM?</h2>\r\n<p>If you're using an older version of SQL, or SQL2008 without FILESTREAM enabled, you have to take other approaches.&nbsp; For inserting data into SQL Server, as you would when saving a zip into the db, you can use the UPDATETEXT verb, following <a href=\"http://msdn.microsoft.com/en-us/library/3517w44b.aspx\">the example given by Microsoft</a>.&nbsp;&nbsp; But there's a catch - with UPDATETEXT your app must provide a buffer that contains the data, which SQL Server then *reads*.&nbsp; Thsi isn't how a DotNetZip save works.&nbsp; So you need a two-step save process:&nbsp; Save the zip to a filesystem file, and then use UPDATETEXT to insert that data into the database. You could also save the zipfile into a MemoryStream.&nbsp; But this of course consumes more memory.&nbsp;</p>\r\n<p>For reading, if you use a SqlDataReader, you can get a <a href=\"http://msdn.microsoft.com/en-us/library/system.data.sqltypes.sqlbytes.stream.aspx\">SqlBytes</a> data type, and that type exposes a Stream property. You can then read from that stream as from any stream.&nbsp; You can then instantiate a ZipFile, passing that stream to the constructor.&nbsp; That will work nicely, if you'd like to extract files from that zip file, into the filesystem.&nbsp; The downside is, <em>I believe,&nbsp;</em> that the SqlBytes.Stream implementation apparently keeps all the&nbsp;varbinary(max) data in memory.&nbsp; So it is&nbsp;a memory hungry implementation.&nbsp; If you have a large zip file, say, 500MB, this may present a problem for you. Putting all that into memory might not be practical.</p>\r\n<p>To avoid that, assuming you are NOT using the FILESTREAM capability, you could extract all the data from SQL Server and write it to a filesystem file.&nbsp; Then instantiate the ZipFile from the file, as normal. You can't use SqlBytes to do the extraction, though - that would cause the same memory consumption problem you're trying to avoid.&nbsp;</p>\r\n<h2>Also consider ZipInputStream</h2>\r\n<p>There's also a forward-only zip stream decorator type in DotNetZip called the ZipInputStream.&nbsp; It wraps around another stream, and can be used to extract zip entries.&nbsp; Consider it an alternative interface to the ZipFile class, specially designed to do read-only operations on zip files. It should work nicely with the SqlBytes.Stream that you obtain from SQL Server, or the SqlFileStream if you have that capability.&nbsp; Where ZipFile provides a random-access capability for the entries in a zip file - in other words you can retrieve entries by name, by size, by anything you like - ZipInputStream provides a sequential access model.&nbsp; For each entry, you can extract it, or skip to the next entry.&nbsp;</p>\r\n<p>You said:</p>\r\n<blockquote style=\"border:solid .1em #ccc;font-style:italic;margin:0.5em 0.5em 0.5em 0.5em;padding:0.5em .25em 0.5em .25em\">I can read back from DB but don't know how to convert back into a Zipfile obj and save back out to file system. I tried to serialize the Zipfile class , but the exception I got was &quot;Not serializable&quot;.</blockquote>\r\n<p>That's a little different than the title of the thread, where you seem to ask about saving a zip INTO sql server.</p>\r\n<p>I don't understand what part you&nbsp;are saving into the filesystem.&nbsp; If you only want to save the zipfile into the filesystem, then you can just read from SQL Server, and copy those bytes into a &nbsp;filesystem file, and name the file with the .zip extension.&nbsp; That's clear, right?&nbsp; If you want to extract from the zip file, then you can follow the suggestions I gave above.</p>\r\n<p>I hope this is helpful.</p>\r\n<p>Good luck.</p>\r\n<p>&nbsp;</p>\r\n<p>&nbsp;</p>",
    "PostedDate": "2010-03-16T22:07:13.59-07:00",
    "UserRole": null,
    "MarkedAsAnswerDate": null
  }
]