在ASP.NET中實現壓縮多個文件爲.zip文件,實現批量下載功能 (轉載並優化處理篇)

轉自:http://blog.csdn.net/yanlele424/article/details/6895986html

 這段時間一直在作一個網站,其中遇到了一個問題,就是在服務器端壓縮多個服務器端的文件,而後在供客戶下載。說白了就是用戶上傳了多個文件,而後別的用戶能夠點擊批量下載這些文件。我要作的就是實現把這些文件壓縮以後供用戶下載。         我首先想到的是.Net提供的GZipStream類,翻了一下書才發現GZipStream沒有提供加壓多個文件的方法,須要本身定義,這樣解壓也只有使用本身的程序才能夠。這不是我想要的效果,放棄這個方案。因爲以前沒有接觸過這方面的技術,只有在網上找,結果找到多種解決的方案,大部分的方法都要使用外部的類庫。這裏列出來一個最經常使用的,以備之後查找方便: SharpZipLib (參見文章http://www.cnblogs.com/tuyile006/archive/2008/04/25/1170894.htmljava

 

使用ICSharpCode.SharpZipLib.dll;     下載地址    http://www.icsharpcode.net/OpenSource/SharpZipLib/Download.aspxweb

下面是對#ZipLib進行.net下的解壓縮的方法的介紹。                  1.BZip2                加入ICSharpCode.SharpZipLib.dll的引用,在#Develop的安裝目錄下的\SharpDevelop\bin目錄下。而後在程序中使用using語句把BZip2          類庫包含進來。        壓縮:使用BZip2的靜態方法Compress。                它的第一個參數是所要壓縮的文件所表明的輸入流,可使用System.IO.File的靜態方法OpenRead。               第二個參數是要創建的壓縮文件所表明的輸出流,可使用System.IO.File的靜態方法Create建立,壓縮文件名是所要壓縮文件的文件名          加上壓縮後綴.bz(一樣你也能夠取其餘的文件名)。                第三個參數是要壓縮的塊大小(通常爲2048的整數)。             解壓:使用BZip2的靜態方法Decompress。                它的第一個參數是所要解壓的壓縮文件所表明的輸入流,可使用System.IO.File的靜態方法OpenRead。               第二個參數是要創建的解壓文件所表明的輸出流,可使用System.IO.File的靜態方法Create建立,由於解壓文件的文件名是去掉了壓縮          文件擴展名的壓縮文件名(你也能夠作成解壓文件與壓縮文件不一樣名的)。        編譯你的程序,而後在命令行方式下輸入bzip2   文件名(假設創建的C#文件是bzip2,就能夠生成壓縮文件;輸入bzip2   -d   文件名,就會解壓          出文件來(-d是用來表示解壓,你也可使用其餘的符號)。        呵呵,原來作壓縮能夠這麼簡單的,壓縮效果也能夠啊。     
  1. using   System;       
  2.  using   System.IO;       
  3.  using   ICSharpCode.SharpZipLib.BZip2;       
  4.      
  5.  class   MainClass       
  6.  {       
  7.        public   static   void   Main(string[]   args)       
  8.        {       
  9.              if   (args[0]   ==   "-d")   {   //   解壓       
  10.                    BZip2.Decompress(File.OpenRead(args[1]),   File.Create(Path.GetFileNameWithoutExtension(args[1])));       
  11.              }   else   {   //壓縮       
  12.                    BZip2.Compress(File.OpenRead(args[0]),   File.Create(args[0]   +   ".bz"),   4096);       
  13.              }       
  14.        }       
  15.  }       
  2.GZip                加入ICSharpCode.SharpZipLib.dll的引用,在#Develop的安裝目錄下的\SharpDevelop\bin目錄下。而後在程序中使用using語句把GZip類          庫包含進來。                因爲GZip沒有BZip2的簡單解壓縮方法,所以只能使用流方法來進行解壓縮。具體的方法見程序的說明。             編譯程序,而後在命令行方式下輸入GZip   文件名(假設創建的C#文件是GZip,就能夠生成壓縮文件;輸入GZip   -d   文件名,就會解壓出文          件來(-d是用來表示解壓,你也可使用其餘的符號)。       
  1. using   System;       
  2.  using   System.IO;       
  3.      
  4.  using   ICSharpCode.SharpZipLib.GZip;       
  5.      
  6.  class   MainClass       
  7.  {       
  8.        public   static   void   Main(string[]   args)       
  9.        {       
  10.              if   (args[0]   ==   "-d")   {   //   解壓       
  11.                    Stream   s   =   new   GZipInputStream(File.OpenRead(args[1]));       
  12.                    //生成一個GZipInputStream流,用來打開壓縮文件。       
  13.                  //由於GZipInputStream由Stream派生,因此它能夠賦給Stream。       
  14.                      //它的構造函數的參數是一個表示要解壓的壓縮文件所表明的文件流       
  15.                    FileStream   fs   =   File.Create(Path.GetFileNameWithoutExtension(args[1]));       
  16.                    //生成一個文件流,它用來生成解壓文件       
  17.                    //可使用System.IO.File的靜態函數Create來生成文件流       
  18.                    int   size   =   2048;//指定壓縮塊的大小,通常爲2048的倍數       
  19.                    byte[]   writeData   =   new   byte[size];//指定緩衝區的大小       
  20.                    while   (true)   {       
  21.                          size   =   s.Read(writeData,   0,   size);//讀入一個壓縮塊       
  22.                          if   (size   >   0)   {       
  23.                                fs.Write(writeData,   0,   size);//寫入解壓文件表明的文件流       
  24.                          }   else   {       
  25.                                break;//若讀到壓縮文件尾,則結束       
  26.                          }       
  27.                    }       
  28.                    s.Close();       
  29.              }   else   {   //   壓縮       
  30.                    Stream   s   =   new   GZipOutputStream(File.Create(args[0]   +   ".gz"));       
  31.                    //生成一個GZipOutputStream流,用來生成壓縮文件。       
  32.                                                  //由於GZipOutputStream由Stream派生,因此它能夠賦給Stream。       
  33.                      FileStream   fs   =   File.OpenRead(args[0]);       
  34.                    /生成一個文件流,它用來打開要壓縮的文件       
  35.                    //可使用System.IO.File的靜態函數OpenRead來生成文件流       
  36.                    byte[]   writeData   =   new   byte[fs.Length];       
  37.                    //指定緩衝區的大小       
  38.                    fs.Read(writeData,   0,   (int)fs.Length);       
  39.                    //讀入文件       
  40.                    s.Write(writeData,   0,   writeData.Length);       
  41.                    //寫入壓縮文件       
  42.                    s.Close();       
  43.                    //關閉文件       
  44.              }       
  45.        }       
  46.  }   

   使用這個類庫當然好,可是也有些缺陷,它只能壓縮文件夾第一級子目錄中的「文件」(不包括文件夾和子目錄)的狀況,這也不能知足個人要求,我想要的是能夠壓縮任意路徑的多個文件。       沒辦法,只好再想別的辦法。鬱悶了好久以後在別人的一篇文章中終於找到了靈感,別人的一篇文章是寫在java中實現壓縮zip文件,我看了後發如今java中實現壓縮爲zip文件很容易。靈機一動我想到了.net中的J#,J#中應該有java中的這樣類,若是有的話,那麼我在個人C#程序中就能夠引用了(利用.net特有的語言互操做性)。因而我就上網搜這方面的內容,終於在MSDN中找到了這樣的例子服務器

http://msdn.microsoft.com/en-gb/library/aa686114(zh-cn).aspx#EHAA得來全不費功夫啊),貼出來找到的代碼,你們共同窗習。app

 

  1. using System;  
  2. using System.Collections;  
  3. using java.util;  
  4. using java.util.zip;  
  5.   
  6. namespace CsZip  
  7. {  
  8.     public delegate Enumeration EnumerationMethod();  
  9.   
  10.     /// <summary>  
  11.     /// Wraps java enumerators   
  12.     /// </summary>  
  13.     public class EnumerationAdapter : IEnumerable  
  14.     {  
  15.         private class EnumerationWrapper : IEnumerator  
  16.         {  
  17.             private EnumerationMethod m_Method;  
  18.             private Enumeration m_Wrapped;  
  19.             private object m_Current;  
  20.   
  21.             public EnumerationWrapper(EnumerationMethod method)  
  22.             {  
  23.                 m_Method = method;  
  24.             }  
  25.   
  26.             // IEnumerator  
  27.             public object Current  
  28.             {  
  29.                 get { return m_Current; }  
  30.             }  
  31.   
  32.             public void Reset()  
  33.             {  
  34.                 m_Wrapped = m_Method();  
  35.                 if (m_Wrapped == null)  
  36.                     throw new InvalidOperationException();  
  37.             }  
  38.   
  39.             public bool MoveNext()  
  40.             {  
  41.                 if (m_Wrapped == null)  
  42.                     Reset();  
  43.                 bool Result = m_Wrapped.hasMoreElements();  
  44.                 if (Result)  
  45.                     m_Current = m_Wrapped.nextElement();  
  46.                 return Result;  
  47.             }  
  48.         }  
  49.   
  50.         private EnumerationMethod m_Method;  
  51.   
  52.         public EnumerationAdapter(EnumerationMethod method)  
  53.         {  
  54.             if (method == null)  
  55.                 throw new ArgumentException();  
  56.             m_Method = method;  
  57.         }  
  58.   
  59.         // IEnumerable  
  60.         public IEnumerator GetEnumerator()  
  61.         {  
  62.             return new EnumerationWrapper(m_Method);  
  63.         }  
  64.     }  
  65.   
  66.     public delegate bool FilterEntryMethod(ZipEntry e);  
  67.   
  68.     /// <summary>  
  69.     /// Zip stream utils  
  70.     /// </summary>  
  71.     public class ZipUtility  
  72.     {  
  73.         public static void CopyStream(java.io.InputStream from, java.io.OutputStream to)  
  74.         {  
  75.             sbyte[] buffer = new sbyte[8192];  
  76.             int got;  
  77.             while ((got = from.read(buffer, 0, buffer.Length)) > 0)  
  78.                 to.write(buffer, 0, got);  
  79.         }  
  80.   
  81.         public static void ExtractZipFile(ZipFile file, string path, FilterEntryMethod filter)  
  82.         {  
  83.             foreach (ZipEntry entry in new EnumerationAdapter(new EnumerationMethod(file.entries)))  
  84.             {  
  85.                 if (!entry.isDirectory())  
  86.                 {  
  87.                     if ((filter == null || filter(entry)))  
  88.                     {  
  89.                         java.io.InputStream s = file.getInputStream(entry);  
  90.                         try  
  91.                         {  
  92.                             string fname = System.IO.Path.GetFileName(entry.getName());  
  93.                             string newpath = System.IO.Path.Combine(path, System.IO.Path.GetDirectoryName(entry.getName()));  
  94.   
  95.                             System.IO.Directory.CreateDirectory(newpath);  
  96.   
  97.                             java.io.FileOutputStream dest = new java.io.FileOutputStream(System.IO.Path.Combine(newpath, fname));  
  98.                             try  
  99.                             {  
  100.                                 CopyStream(s, dest);  
  101.                             }  
  102.                             finally  
  103.                             {  
  104.                                 dest.close();  
  105.                             }  
  106.                         }  
  107.                         finally  
  108.                         {  
  109.                             s.close();  
  110.                         }  
  111.                     }  
  112.                 }  
  113.             }  
  114.         }  
  115.   
  116.         /// <summary>  
  117.         /// 建立新的Zip文件  
  118.         /// </summary>  
  119.         /// <param name="fileName">Zip文件的路徑</param>  
  120.         /// <returns>Zip文件的路徑</returns>  
  121.         public static ZipFile CreateEmptyZipFile(string fileName)  
  122.         {  
  123.             new ZipOutputStream(new java.io.FileOutputStream(fileName)).close();  
  124.             return new ZipFile(fileName);  
  125.         }  
  126.   
  127.         /// <summary>  
  128.         /// 向存在的Zip文件中添加待壓縮的文件  
  129.         /// </summary>  
  130.         /// <param name="file">Zip文件</param>  
  131.         /// <param name="filter"></param>  
  132.         /// <param name="newFiles">待壓縮的文件的路徑</param>  
  133.         /// <returns></returns>  
  134.         public static ZipFile UpdateZipFile(ZipFile file, FilterEntryMethod filter, string[] newFiles)  
  135.         {  
  136.             string prev = file.getName();  
  137.             string tmp = System.IO.Path.GetTempFileName();  
  138.             ZipOutputStream to = new ZipOutputStream(new java.io.FileOutputStream(tmp));  
  139.             try  
  140.             {  
  141.                 CopyEntries(file, to, filter);  
  142.                 // add entries here  
  143.                 if (newFiles != null)  
  144.                 {  
  145.                     foreach (string f in newFiles)  
  146.                     {  
  147.                         ZipEntry z = new ZipEntry(f.Remove(0, System.IO.Path.GetPathRoot(f).Length));  
  148.                         z.setMethod(ZipEntry.DEFLATED);  
  149.                         to.putNextEntry(z);  
  150.                         try  
  151.                         {  
  152.                             java.io.FileInputStream s = new java.io.FileInputStream(f);  
  153.                             try  
  154.                             {  
  155.                                 CopyStream(s, to);  
  156.                             }  
  157.                             finally  
  158.                             {  
  159.                                 s.close();  
  160.                             }  
  161.                         }  
  162.                         finally  
  163.                         {  
  164.                             to.closeEntry();  
  165.                         }  
  166.                     }  
  167.                 }  
  168.             }  
  169.             finally  
  170.             {  
  171.                 to.close();  
  172.             }  
  173.             file.close();  
  174.   
  175.             // now replace the old file with the new one  
  176.             System.IO.File.Copy(tmp, prev, true);  
  177.             System.IO.File.Delete(tmp);  
  178.   
  179.             return new ZipFile(prev);  
  180.         }  
  181.   
  182.         public static void CopyEntries(ZipFile from, ZipOutputStream to)  
  183.         {  
  184.             CopyEntries(from, to, null);  
  185.         }  
  186.   
  187.         public static void CopyEntries(ZipFile from, ZipOutputStream to, FilterEntryMethod filter)  
  188.         {  
  189.             foreach (ZipEntry entry in new EnumerationAdapter(new EnumerationMethod(from.entries)))  
  190.             {  
  191.                 if (filter == null || filter(entry))  
  192.                 {  
  193.                     java.io.InputStream s = from.getInputStream(entry);  
  194.                     try  
  195.                     {  
  196.                         to.putNextEntry(entry);  
  197.                         try  
  198.                         {  
  199.                             CopyStream(s, to);  
  200.                         }  
  201.                         finally  
  202.                         {  
  203.                             to.closeEntry();  
  204.                         }  
  205.                     }  
  206.                     finally  
  207.                     {  
  208.                         s.close();  
  209.                     }  
  210.                 }  
  211.             }  
  212.         }  
  213.     }  
  214. }  

使用國外開源加壓解壓庫ICSharpCode.SharpZipLib實現加壓,該庫的官方網站爲函數

http://www.icsharpcode.net/OpenSource/SharpZipLib/Download.aspxoop

使用體驗:能夠照着例子實現簡單的加壓解壓,能夠加壓一個文件夾中的全部文件,但沒有提供加壓子文件夾的說明。 目前網上的一些代碼有的沒法加壓空文件夾,有的加壓了用rar解不開,這是一點須要改進的。 但若是隻須要加壓文件夾第一級子目錄中的「文件」(不包括文件夾和子目錄)的狀況,使用這個庫是很方便的。並且是正常zip格式。 比.Net提供的GZipStream類強在它能夠按照標準zip格式加壓多個文件,而GZipStream沒有提供加壓多個文件的方法,須要本身定義, 這樣解壓也只有使用本身的程序才能夠,通用性方面不如SharpZipLib。學習

  1. #region 加壓解壓方法  
  2.         /// <summary>  
  3.         /// 功能:壓縮文件(暫時只壓縮文件夾下一級目錄中的文件,文件夾及其子級被忽略)  
  4.         /// </summary>  
  5.         /// <param name="dirPath">被壓縮的文件夾夾路徑</param>  
  6.         /// <param name="zipFilePath">生成壓縮文件的路徑,爲空則默認與被壓縮文件夾同一級目錄,名稱爲:文件夾名+.zip</param>  
  7.         /// <param name="err">出錯信息</param>  
  8.         /// <returns>是否壓縮成功</returns>  
  9.         public bool ZipFile(string dirPath, string zipFilePath, out string err)  
  10.         {  
  11.             err = "";  
  12.             if (dirPath == string.Empty)  
  13.             {  
  14.                 err = "要壓縮的文件夾不能爲空!";  
  15.                 return false;  
  16.             }  
  17.             if (!Directory.Exists(dirPath))  
  18.             {  
  19.                 err = "要壓縮的文件夾不存在!";  
  20.                 return false;  
  21.             }  
  22.             //壓縮文件名爲空時使用文件夾名+.zip  
  23.             if (zipFilePath == string.Empty)  
  24.             {  
  25.                 if (dirPath.EndsWith("\\"))  
  26.                 {  
  27.                     dirPath = dirPath.Substring(0, dirPath.Length - 1);  
  28.                 }  
  29.                 zipFilePath = dirPath + ".zip";  
  30.             }  
  31.   
  32.             try  
  33.             {  
  34.                 string[] filenames = Directory.GetFiles(dirPath);  
  35.                 using (ZipOutputStream s = new ZipOutputStream(File.Create(zipFilePath)))  
  36.                 {  
  37.                     s.SetLevel(9);  
  38.                     byte[] buffer = new byte[4096];  
  39.                     foreach (string file in filenames)  
  40.                     {  
  41.                         ZipEntry entry = new ZipEntry(Path.GetFileName(file));  
  42.                         entry.DateTime = DateTime.Now;  
  43.                         s.PutNextEntry(entry);  
  44.                         using (FileStream fs = File.OpenRead(file))  
  45.                         {  
  46.                             int sourceBytes;  
  47.                             do  
  48.                             {  
  49.                                 sourceBytes = fs.Read(buffer, 0, buffer.Length);  
  50.                                 s.Write(buffer, 0, sourceBytes);  
  51.                             } while (sourceBytes > 0);  
  52.                         }  
  53.                     }  
  54.                     s.Finish();  
  55.                     s.Close();  
  56.                 }  
  57.             }  
  58.             catch (Exception ex)  
  59.             {  
  60.                 err = ex.Message;  
  61.                 return false;  
  62.             }  
  63.             return true;  
  64.         }  
  65.   
  66.         /// <summary>  
  67.         /// 功能:解壓zip格式的文件。  
  68.         /// </summary>  
  69.         /// <param name="zipFilePath">壓縮文件路徑</param>  
  70.         /// <param name="unZipDir">解壓文件存放路徑,爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾</param>  
  71.         /// <param name="err">出錯信息</param>  
  72.         /// <returns>解壓是否成功</returns>  
  73.         public bool UnZipFile(string zipFilePath, string unZipDir, out string err)  
  74.         {  
  75.             err = "";  
  76.             if (zipFilePath == string.Empty)  
  77.             {  
  78.                 err = "壓縮文件不能爲空!";  
  79.                 return false;  
  80.             }  
  81.             if (!File.Exists(zipFilePath))  
  82.             {  
  83.                 err = "壓縮文件不存在!";  
  84.                 return false;  
  85.             }  
  86.             //解壓文件夾爲空時默認與壓縮文件同一級目錄下,跟壓縮文件同名的文件夾  
  87.             if (unZipDir == string.Empty)  
  88.                 unZipDir = zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));  
  89.             if (!unZipDir.EndsWith("\\"))  
  90.                 unZipDir += "\\";  
  91.             if (!Directory.Exists(unZipDir))  
  92.                 Directory.CreateDirectory(unZipDir);  
  93.   
  94.             try  
  95.             {  
  96.                 using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipFilePath)))  
  97.                 {  
  98.   
  99.                     ZipEntry theEntry;  
  100.                     while ((theEntry = s.GetNextEntry()) != null)  
  101.                     {  
  102.                         string directoryName = Path.GetDirectoryName(theEntry.Name);  
  103.                         string fileName = Path.GetFileName(theEntry.Name);  
  104.                         if (directoryName.Length > 0)  
  105.                         {  
  106.                             Directory.CreateDirectory(unZipDir + directoryName);  
  107.                         }  
  108.                         if (!directoryName.EndsWith("\\"))  
  109.                             directoryName += "\\";  
  110.                         if (fileName != String.Empty)  
  111.                         {  
  112.                             using (FileStream streamWriter = File.Create(unZipDir + theEntry.Name))  
  113.                             {  
  114.   
  115.                                 int size = 2048;  
  116.                                 byte[] data = new byte[2048];  
  117.                                 while (true)  
  118.                                 {  
  119.                                     size = s.Read(data, 0, data.Length);  
  120.                                     if (size > 0)  
  121.                                     {  
  122.                                         streamWriter.Write(data, 0, size);  
  123.                                     }  
  124.                                     else  
  125.                                     {  
  126.                                         break;  
  127.                                     }  
  128.                                 }  
  129.                             }  
  130.                         }  
  131.                     }//while  
  132.                 }  
  133.             }  
  134.             catch (Exception ex)  
  135.             {  
  136.                 err = ex.Message;  
  137.                 return false;  
  138.             }  
  139.             return true;  
  140.         }//解壓結束  
  141.         #endregion  

 須要添加對SharpZipLib的引用:網站

using ICSharpCode.SharpZipLib.Zip;
相關文章
相關標籤/搜索