SharpZipLib and ASP.NET
I recently had to write a search-driven component to extract and export documents from a SharePoint repository. It presented a challenge since many examples on the web start from the premise of a file system and not binary streams.
I settled upon SharpZipLib, an excellent and fairly easy to use library, but found the documentation quite lacking, particularly around creating a zip file to a stream (like an ASP.NET output response stream).
I put together a little sample just to test it out and finally got it working after struggling with it for a good 30 minutes. This sample creates a zip package using an embedded resource (text file) for simplicity. In practice, you can just modify the implementation of the GetBinaryContent helper method. Note that when adding multiple files, you do a “put” first and then a “write”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
<span style="font-family: Lucida Console;"><span style="color: #0000ff;">using </span><span style="color: #008080;">System</span><span style="color: #000000;">;</span> <span style="color: #0000ff;">using </span><span style="color: #008080;">System</span><span style="color: #000000;">.</span><span style="color: #008080;">IO</span><span style="color: #000000;">;</span> <span style="color: #0000ff;">using </span><span style="color: #008080;">System</span><span style="color: #000000;">.</span><span style="color: #008080;">Reflection</span><span style="color: #000000;">;</span> <span style="color: #0000ff;">using </span><span style="color: #008080;">System</span><span style="color: #000000;">.</span><span style="color: #008080;">Web</span><span style="color: #000000;">;</span> <span style="color: #0000ff;">using </span><span style="color: #008080;">System</span><span style="color: #000000;">.</span><span style="color: #008080;">Web</span><span style="color: #000000;">.</span><span style="color: #008080;">UI</span><span style="color: #000000;">;</span> <span style="color: #0000ff;">using </span><span style="color: #000000;">ICSharpCode.SharpZipLib.Zip;</span></span> <span style="font-family: Lucida Console;"><span style="color: #0000ff;">namespace </span><span style="color: #000000;">SharpZipLibTest {</span> <span style="color: #0000ff;">public </span><span style="color: #000000;">partial </span><span style="color: #0000ff;">class </span><span style="color: #000000;">_Default : </span><span style="color: #808000;">Page </span><span style="color: #000000;">{</span> <span style="color: #0000ff;">protected void </span><span style="color: #000000;">Page_Load(</span><span style="color: #0000ff;">object </span><span style="color: #000000;">sender, </span><span style="color: #808000;">EventArgs </span><span style="color: #000000;">e) {</span> <span style="color: #0000ff;">string </span><span style="color: #000000;">fileName = </span><span style="color: #ff00ff;">"package.zip"</span><span style="color: #000000;">;</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">// Clear the response.</span> <span style="color: #000000;">Response.Clear();</span> <span style="color: #000000;">Response.</span><span style="color: #808000;">Buffer </span><span style="color: #000000;">= </span><span style="color: #0000ff;">true</span><span style="color: #000000;">;</span> <span style="color: #000000;">Response.ContentType = </span><span style="color: #ff00ff;">"application/octet-stream"</span><span style="color: #000000;">;</span> <span style="color: #000000;">Response.Charset = </span><span style="color: #ff00ff;">""</span><span style="color: #000000;">;</span> <span style="color: #000000;">Response.AddHeader(</span><span style="color: #ff00ff;">"Content-Disposition"</span><span style="color: #000000;">,</span> <span style="color: #0000ff;">string</span><span style="color: #000000;">.Format(</span><span style="color: #ff00ff;">"attachment; filename={0}"</span><span style="color: #000000;">, fileName));</span></span> <span style="font-family: Lucida Console;"> <span style="color: #0000ff;">using </span><span style="color: #000000;">(var ms = </span><span style="color: #0000ff;">new </span><span style="color: #808000;">MemoryStream</span><span style="color: #000000;">()) </span> <span style="color: #0000ff;">using </span><span style="color: #000000;">(var zip = </span><span style="color: #0000ff;">new </span><span style="color: #000000;">ZipOutputStream(ms)) {</span> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[] fileBuffer = GetBinaryContent();</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">// Write to the zip package.</span> <span style="color: #000000;">var entry = </span><span style="color: #0000ff;">new </span><span style="color: #000000;">ZipEntry(</span><span style="color: #ff00ff;">"helloworld.txt"</span><span style="color: #000000;">);</span> <span style="color: #000000;">entry.</span><span style="color: #808000;">DateTime </span><span style="color: #000000;">= </span><span style="color: #808000;">DateTime</span><span style="color: #000000;">.Now;</span> <span style="color: #000000;">entry.</span><span style="color: #808000;">Size </span><span style="color: #000000;">= fileBuffer.Length;</span> <span style="color: #000000;">zip.PutNextEntry(entry);</span> <span style="color: #000000;">zip.Write(fileBuffer, </span><span style="color: #800080;">0</span><span style="color: #000000;">, fileBuffer.Length);</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">// Repeat for each file</span> <span style="color: #008000;">/*</span> <span style="color: #008000;"> for(...) {</span> <span style="color: #008000;"> var entry = new ZipEntry("...");</span></span> <span style="font-family: Lucida Console;"><span style="color: #008000;"> zip.PutNextEntry(entry);</span> <span style="color: #008000;"> zip.Write(...);</span> <span style="color: #008000;"> }</span> <span style="color: #008000;"> */</span></span> <span style="font-family: Lucida Console;"> <span style="color: #000000;">zip.Flush();</span> <span style="color: #000000;">zip.Finish();</span></span> <span style="font-family: Lucida Console;"> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[] output = ms.ToArray();</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">// Write the final output to the response stream.</span> <span style="color: #000000;">Response.OutputStream.Write(output, </span><span style="color: #800080;">0</span><span style="color: #000000;">, output.Length); </span> <span style="color: #000000;">}</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">// End the response.</span> <span style="color: #000000;">Response.Flush();</span> <span style="color: #000000;">Response.End();</span></span> <span style="font-family: Lucida Console;"> <span style="color: #808000;">HttpContext</span><span style="color: #000000;">.Current.ApplicationInstance.CompleteRequest();</span> <span style="color: #000000;">}</span></span> <span style="font-family: Lucida Console;"> <span style="color: #008000;">/// <summary></span> <span style="color: #008000;">/// Gets the binary content to send.</span> <span style="color: #008000;">/// </summary></span> <span style="color: #008000;">/// <returns>The byte array containing the binary content.</returns></span> <span style="color: #0000ff;">private byte</span><span style="color: #000000;">[] GetBinaryContent() {</span> <span style="color: #0000ff;">string </span><span style="color: #000000;">resourceName = </span><span style="color: #ff00ff;">"SharpZipLibTest.helloworld.txt"</span><span style="color: #000000;">;</span></span> <span style="font-family: Lucida Console;"> <span style="color: #0000ff;">byte</span><span style="color: #000000;">[] fileBuffer;</span></span> <span style="font-family: Lucida Console;"> <span style="color: #0000ff;">using </span><span style="color: #000000;">(</span><span style="color: #808000;">Stream </span><span style="color: #000000;">s = </span><span style="color: #808000;">Assembly</span><span style="color: #000000;">.GetExecutingAssembly()</span> <span style="color: #000000;">.GetManifestResourceStream(resourceName)) {</span> <span style="color: #008000;">// Read the file stream into a buffer.</span> <span style="color: #000000;">fileBuffer = </span><span style="color: #0000ff;">new byte</span><span style="color: #000000;">[s.Length];</span></span> <span style="font-family: Lucida Console;"> <span style="color: #000000;">s.Read(fileBuffer, </span><span style="color: #800080;">0</span><span style="color: #000000;">, fileBuffer.Length);</span> <span style="color: #000000;">}</span></span> <span style="font-family: Lucida Console;"> <span style="color: #0000ff;">return </span><span style="color: #000000;">fileBuffer;</span> <span style="color: #000000;">}</span> <span style="color: #000000;">}</span> <span style="color: #000000;">}</span></span> |
The full project file is attached and runnable.