2009-03-25 30 views
23

¿Necesitas empaquetar dinámicamente algunos archivos en un .zip para crear un paquete SCORM, cualquiera sabe cómo se puede hacer esto usando el código? ¿Es posible construir la estructura de carpetas dinámicamente dentro de .zip también?¿Cómo crear y llenar un archivo ZIP utilizando ASP.NET?

+0

Posible duplicado de [Usando System.IO.Packaging para generar un archivo ZIP] (http://stackoverflow.com/questions/6386113/using-system-io-packaging-to-generate-a-zip-file) – Will

Respuesta

14

Ya no es necesario que use una biblioteca externa. System.IO.Packaging tiene clases que se pueden usar para colocar contenido en un archivo zip. No es simple, sin embargo. Here's a blog post with an example (está al final; excavar para obtenerlo).


El enlace no es estable, así que aquí está el ejemplo que Jon proporcionó en la publicación.

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 para el enlace extremadamente útil que el autor mantiene actualizado. –

+0

También eche un vistazo a este enlace http://weblogs.asp.net/dneimke/archive/2005/02/25/380273.aspx – daitangio

+0

El enlace está roto – bpoiss

1

He usado un componente gratuito de chilkat para esto: http://www.chilkatsoft.com/zip-dotnet.asp. Hace casi todo lo que he necesitado; sin embargo, no estoy seguro sobre cómo construir dinámicamente la estructura de archivos.

+0

Utilizamos también este componente en nuestra empresa. Basado en errores en el componente, algunos de nuestros servicios extremadamente estresados ​​causaron una EngineException. Después de un Boleto de soporte de Microsoft, decidimos cambiar a SharpZLib. Esto fue hace 2 años. No sé qué tan bueno es el componente hoy en día? –

+0

Nunca hemos tenido ningún problema, sin embargo, se usa en los servicios de exportación que, por lo general, se ejecutan como máximo cada hora, pero por lo general a diario.El cifrado también es útil – Macros

20

DotNetZip es bueno para esto. Working example

Puede escribir el zip directamente en Response.OutputStream. El código se ve así:

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 es gratis.

0

La creación de un archivo ZIP "sobre la marcha" se realizaría utilizando nuestro componente Rebex ZIP.

En el siguiente ejemplo se describe en su totalidad, incluyendo la creación de una subcarpeta:

// 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

Si está utilizando .NET Framework 4.5 o más reciente que puede evitar bibliotecas de terceros y utilizar la clase nativa System.IO.Compression.ZipArchive.

Aquí está un ejemplo de código rápida utilizando un MemoryStream y un par de matrices de bytes que representa dos archivos:

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"); 
} 

Se puede utilizar dentro de un controlador MVC devolver un ActionResult: alternativamente, si es necesario físicamente crear el archivo zip, puede persistir el MemoryStream en el disco o reemplazarlo por completo con un FileStream.

Para obtener más información sobre este tema, también puede read this post.

Cuestiones relacionadas