Saturday, January 13, 2007 6:00 PM bart

Unzipping in ASP.NET

The story

A few days ago I deployed Community Server 2.1 for ASP.NET 2.0 to my web space during maintenance. Everything went just fine, thanks to the wonderful work of Telligent. It's really xcopy deployment and running a few scripts on the SQL Server database. Nevertheless, I was pretty annoyed when I had to upload 3878 files and 320 folders (that's how big the extracted .zip file of CS21 is) under circumstances of Passive FTP and regular connection resets. To summarize, this took a few hours due to the large number of small files and associated data connections for file transfers. (Where's the good old time I just had Terminal Services access to my web server, so that I could download the zip directly on the server and unzip it over there? <g>)

So, I thought to myself, how to overcome this issue? This is the solution I came up with.

 

Unzipping in ASP.NET

The idea: upload the .zip file and extract it on the server. How to do? Using ASP.NET and some library with the rather weird feeling name of java.util.zip. Yes indeed, my first ASP.NET web project with J# is a fact:

Before I continue with the code, I want to stress the following disclaimer:

DISCLAIMER: Run this code at your own risk. Keep in mind you'll be extracting files on a remote web server and you could overwrite files if you're unzipping to the wrong location. I'm not responsible for any possible data loss caused by running this code. You should adapt this code to match your own scenario and fully understand what's going on before pulling the trigger (either by pressing F5 in some way or another, or by hitting the ASP.NET page in question). The code in this article hasn't been subject of thorough testing and therefore should be used with care.

On to the code now. First create the following page:

with two text boxes, called txtZipFile and txtExtractTo. Next, attach an event handler to the Go!-button:

1 protected void btnGo_Click(Object sender, EventArgs e) 2 { 3 String folder = this.get_Server().MapPath(txtExtractTo.get_Text()); 4 System.IO.Directory.CreateDirectory(folder); 5 6 try 7 { 8 java.util.zip.ZipFile file = new java.util.zip.ZipFile(this.get_Server().MapPath(txtZipFile.get_Text())); 9 10 // 11 // List for the directories that are in the zip-file. Will be sorted to deduce the creation order. 12 // 13 ArrayList directories = new ArrayList(); 14 15 // 16 // Look for directory entries in the zip file. 17 // 18 java.util.Enumeration entries = file.entries(); 19 while (entries.hasMoreElements()) 20 { 21 java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.nextElement(); 22 if (entry.isDirectory()) 23 directories.Add(System.IO.Path.Combine(folder, entry.getName())); 24 } 25 26 // 27 // Sort the directory list. This will yield the correct order for creation. 28 // 29 directories.Sort(); 30 31 // 32 // Create the directories. 33 // 34 IEnumerator ie = directories.GetEnumerator(); 35 while (ie.MoveNext()) 36 System.IO.Directory.CreateDirectory((String)ie.get_Current()); 37 38 byte[] buf = new byte[1024]; 39 40 // 41 // Look for file entries in the zip file. 42 // 43 entries = file.entries(); 44 while (entries.hasMoreElements()) 45 { 46 java.util.zip.ZipEntry entry = (java.util.zip.ZipEntry)entries.nextElement(); 47 48 if (!entry.isDirectory()) 49 { 50 // 51 // Get the input stream and create the output stream. 52 // 53 java.io.FileOutputStream fos = new java.io.FileOutputStream(System.IO.Path.Combine(folder, entry.getName())); 54 java.io.InputStream is = file.getInputStream(entry); 55 56 // 57 // Copy the bytes. 58 // 59 int n; 60 while ((n = is.read(buf, 0, 1024)) > -1) 61 fos.write(buf, 0, n); 62 63 // 64 // Clean up. 65 // 66 fos.close(); 67 is.close(); 68 } 69 } 70 71 file.close(); 72 } 73 catch (java.io.IOException ex) 74 { 75 } 76 }

Wow, this should be my first piece of (crappy) Java-code on my blog :-). A few notes on how it works:

  • Line 3: Server.MapPath is called to find the "extract to" location. This folder is created in line 4.
  • Line 8: An instance of java.util.zip.ZipFile is created to manipulate the zip file (more specifically, to read contents from it).
  • Lines 10-36: Find all the folders in the zip file (when is LINQ coming to J# -- I just wanted to write from e in file.entries() where e.isDirectory() order by e.getName() select e.getName()) and create the folders in order (a little trick that seems to work fine).
  • Lines 40-69: Now find the files and extract it to the target folder's subfolder indicated by the zip entry name (basically Path.Combine does all the work for us).
  • Lines 73-74: Some ugliness thanks to these wonderful checked exceptions in the world of Java :-).

Note: This code requires that the server is configured so that the "ASP.NET identity" (ASPNET, the app pool identity, ...) has sufficient rights to create folders and files on your web space (okay over here). The J# runtime should be present on the server machine as well to have access to the java.util.zip library.

Enjoy!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# re: Unzipping in ASP.NET

Sunday, January 14, 2007 7:43 AM by dotnetjunkie

Ugh, I'd rather write my own unzip library in c# than having to resort to Java :-)

But luckily there is no need to do that!

There is this wonderful, free and open source library from the same guys who wrote SharpDevelop: #ziplib!  So yes, it's all in your beloved c#! ;-)

Quote from their website:

#ziplib (SharpZipLib, formerly NZipLib) is a Zip, GZip, Tar and BZip2 library written entirely in C# for the .NET platform. The creator of #ziplib put it this way: "I've ported the zip library over to C# because I needed gzip/zip compression and I didn't want to use libzip.dll or something like this. I want all in pure C#.

Download link: http://www.icsharpcode.net/OpenSource/SharpZipLib/Default.aspx

Have fun!

# re: Unzipping in ASP.NET

Monday, January 15, 2007 3:36 AM by Kai

Why you dont't use the great .NET ZipLib from http://www.icsharpcode.net/OpenSource/SharpZipLib/

# re: Unzipping in ASP.NET

Monday, January 15, 2007 4:32 AM by bart

Hi folks,

I should have know there are ".NET libraries" for zip functionality too, but honestly I didn't even search for it as I knew it was in the java.util.zip namespace, which happens to be one of the implemented namespaces in Microsoft's J#. So, it's still 100% .NET although the idea is expressed in just another language. That's what *Common* Language stands for in CLI/CLR.

-Bart