2009-03-25 22 views
23

È necessario compattare dinamicamente alcuni file in un file .zip per creare un pacchetto SCORM, qualcuno sa come farlo utilizzando il codice? È possibile costruire la struttura delle cartelle dinamicamente anche all'interno di .zip?Come creare e riempire un file ZIP usando ASP.NET?

+0

Possibile duplicato di [Utilizzo di System.IO.Packaging per generare un file ZIP] (http://stackoverflow.com/questions/6386113/using-system-io-packaging-to-generate-a-zip-file) – Will

risposta

14

Non è più necessario utilizzare una libreria esterna. System.IO.Packaging ha classi che possono essere utilizzate per rilasciare il contenuto in un file zip. Non è semplice, tuttavia. Here's a blog post with an example (è alla fine, scavare per esso).


Il collegamento non è stabile, quindi ecco l'esempio fornito da Jon nel post.

using System; 
using System.IO; 
using System.IO.Packaging; 

namespace ZipSample 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      AddFileToZip("Output.zip", @"C:\Windows\Notepad.exe"); 
      AddFileToZip("Output.zip", @"C:\Windows\System32\Calc.exe"); 
     } 

     private const long BUFFER_SIZE = 4096; 

     private static void AddFileToZip(string zipFilename, string fileToAdd) 
     { 
      using (Package zip = System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate)) 
      { 
       string destFilename = ".\\" + Path.GetFileName(fileToAdd); 
       Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative)); 
       if (zip.PartExists(uri)) 
       { 
        zip.DeletePart(uri); 
       } 
       PackagePart part = zip.CreatePart(uri, "",CompressionOption.Normal); 
       using (FileStream fileStream = new FileStream(fileToAdd, FileMode.Open, FileAccess.Read)) 
       { 
        using (Stream dest = part.GetStream()) 
        { 
         CopyStream(fileStream, dest); 
        } 
       } 
      } 
     } 

     private static void CopyStream(System.IO.FileStream inputStream, System.IO.Stream outputStream) 
     { 
      long bufferSize = inputStream.Length < BUFFER_SIZE ? inputStream.Length : BUFFER_SIZE; 
      byte[] buffer = new byte[bufferSize]; 
      int bytesRead = 0; 
      long bytesWritten = 0; 
      while ((bytesRead = inputStream.Read(buffer, 0, buffer.Length)) != 0) 
      { 
       outputStream.Write(buffer, 0, bytesRead); 
       bytesWritten += bytesRead; 
      } 
     } 
    } 
} 
+0

+1 per il link estremamente utile che l'autore sta aggiornando. –

+0

Dai un'occhiata anche a questo link http://weblogs.asp.net/dneimke/archive/2005/02/25/380273.aspx – daitangio

+0

Il link è rotto – bpoiss

1

Ho usato un componente gratuito da chilkat per questo: http://www.chilkatsoft.com/zip-dotnet.asp. Fa praticamente tutto ciò di cui ho bisogno, ma non sono sicuro di costruire la struttura dei file in modo dinamico.

+0

Abbiamo usato questo componente anche nella nostra azienda. Sulla base degli errori nel componente, alcuni dei nostri servizi estremamente stressati hanno causato una EngineException. Dopo un ticket di supporto Microsoft, abbiamo deciso di passare a SharpZLib. Questo era 2 anni fa. Non so quanto sia buono il componente oggi? –

+0

Non abbiamo mai avuto problemi con esso, tuttavia viene utilizzato nei servizi di esportazione che generalmente vengono eseguiti al massimo ogni ora, ma in genere ogni giorno.La crittografia è utile anche per – Macros

20

DotNetZip è bello per questo. Working example

È possibile scrivere lo zip direttamente su Response.OutputStream. Il codice è simile al seguente:

Response.Clear(); 
    Response.BufferOutput = false; // for large files... 
    System.Web.HttpContext c= System.Web.HttpContext.Current; 
    String ReadmeText= "Hello!\n\nThis is a README..." + DateTime.Now.ToString("G"); 
    string archiveName= String.Format("archive-{0}.zip", 
             DateTime.Now.ToString("yyyy-MMM-dd-HHmmss")); 
    Response.ContentType = "application/zip"; 
    Response.AddHeader("content-disposition", "filename=" + archiveName); 

    using (ZipFile zip = new ZipFile()) 
    { 
     // filesToInclude is an IEnumerable<String>, like String[] or List<String> 
     zip.AddFiles(filesToInclude, "files");    

     // Add a file from a string 
     zip.AddEntry("Readme.txt", "", ReadmeText); 
     zip.Save(Response.OutputStream); 
    } 
    // Response.End(); // no! See http://stackoverflow.com/questions/1087777 
    Response.Close(); 

DotNetZip è gratuito.

0

La creazione del file ZIP "al volo" avverrà utilizzando il nostro componente Rebex ZIP.

L'esempio seguente descrive pienamente, compresa la creazione di una sottocartella:

// prepare MemoryStream to create ZIP archive within 
using (MemoryStream ms = new MemoryStream()) 
{ 
    // create new ZIP archive within prepared MemoryStream 
    using (ZipArchive zip = new ZipArchive(ms)) 
    {    
     // add some files to ZIP archive 
     zip.Add(@"c:\temp\testfile.txt"); 
     zip.Add(@"c:\temp\innerfile.txt", @"\subfolder"); 

     // clear response stream and set the response header and content type 
     Response.Clear(); 
     Response.ContentType = "application/zip"; 
     Response.AddHeader("content-disposition", "filename=sample.zip"); 

     // write content of the MemoryStream (created ZIP archive) to the response stream 
     ms.WriteTo(Response.OutputStream); 
    } 
} 

// close the current HTTP response and stop executing this page 
HttpContext.Current.ApplicationInstance.CompleteRequest(); 
0

Se si utilizza .NET Framework 4.5 o più recente si può evitare le librerie di terze parti e utilizzare la classe nativa System.IO.Compression.ZipArchive.

Ecco un esempio di codice rapido utilizzando un MemoryStream e un paio di array di byte che rappresenta due file:

byte[] file1 = GetFile1ByteArray(); 
byte[] file2 = GetFile2ByteArray(); 

using (MemoryStream ms = new MemoryStream()) 
{ 
    using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true)) 
    { 
     var zipArchiveEntry = archive.CreateEntry("file1.txt", CompressionLevel.Fastest); 
     using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file1, 0, file1.Length); 
     zipArchiveEntry = archive.CreateEntry("file2.txt", CompressionLevel.Fastest); 
     using (var zipStream = zipArchiveEntry.Open()) zipStream.Write(file2, 0, file2.Length); 
    } 
    return File(ms.ToArray(), "application/zip", "Archive.zip"); 
} 

è possibile utilizzarlo all'interno di un controller MVC la restituzione di un ActionResult: In alternativa, se è necessario fisicamente creare il archivio zip, è possibile persistere il MemoryStream su disco o interamente sostituirlo con uno FileStream.

Per ulteriori informazioni su questo argomento è inoltre possibile read this post.

Problemi correlati