Extraer archivos de un archivo Zip mediante programación mediante C#y System.IO.Packaging
(6)
Desde MSDN ,
En esta muestra, se usa la clase Paquete (a diferencia del ZipPackage). Después de haber trabajado con ambos, solo he visto que se produce flakiness cuando hay corrupción en el archivo zip. No necesariamente la corrupción que arroja el extractor de Windows o Winzip, pero algo que los componentes de embalaje tienen problemas para manejar.
Espero que esto ayude, tal vez puede brindarte una alternativa a la depuración del problema.
using System;
using System.IO;
using System.IO.Packaging;
using System.Text;
class ExtractPackagedImages
{
static void Main(string[] paths)
{
foreach (string path in paths)
{
using (Package package = Package.Open(
path, FileMode.Open, FileAccess.Read))
{
DirectoryInfo dir = Directory.CreateDirectory(path + " Images");
foreach (PackagePart part in package.GetParts())
{
if (part.ContentType.ToLowerInvariant().StartsWith("image/"))
{
string target = Path.Combine(
dir.FullName, CreateFilenameFromUri(part.Uri));
using (Stream source = part.GetStream(
FileMode.Open, FileAccess.Read))
using (Stream destination = File.OpenWrite(target))
{
byte[] buffer = new byte[0x1000];
int read;
while ((read = source.Read(buffer, 0, buffer.Length)) > 0)
{
destination.Write(buffer, 0, read);
}
}
Console.WriteLine("Extracted {0}", target);
}
}
}
}
Console.WriteLine("Done");
}
private static string CreateFilenameFromUri(Uri uri)
{
char [] invalidChars = Path.GetInvalidFileNameChars();
StringBuilder sb = new StringBuilder(uri.OriginalString.Length);
foreach (char c in uri.OriginalString)
{
sb.Append(Array.IndexOf(invalidChars, c) < 0 ? c : ''_'');
}
return sb.ToString();
}
}
Tengo un montón de archivos ZIP que necesitan desesperadamente alguna reorganización y extracción jerárquica. Lo que puedo hacer, actualmente, es crear la estructura del directorio y mover los archivos zip a la ubicación correcta. El queso místico que me falta es la parte que extrae los archivos del archivo ZIP.
He visto los artículos de MSDN en la clase ZipArchive
y los entiendo bastante bien. También he visto las formas de VBScript de extraer . Esta no es una clase compleja, por lo que extraer cosas debería ser bastante simple. De hecho, funciona "principalmente". He incluido mi código actual a continuación para referencia.
using (ZipPackage package = (ZipPackage)Package.Open(@"../../test.zip", FileMode.Open, FileAccess.Read))
{
PackagePartCollection packageParts = package.GetParts();
foreach (PackageRelationship relation in packageParts)
{
//Do Stuff but never gets here since packageParts is empty.
}
}
El problema parece estar en algún lugar de GetParts
(o Get Anything para ese asunto). Parece que el paquete, mientras está abierto, está vacío. Profundizando más, el depurador muestra que el miembro privado _zipArchive muestra que en realidad tiene partes. Partes con los nombres correctos y todo. ¿Por qué la función GetParts
no los recuperará? Intenté abrir el archivo ZipArchive y eso no ayudó. Grrr.
Estoy de acuerdo con Cheeso. System.IO.Packaging es incómodo cuando se manejan archivos zip genéricos, ya que fue diseñado para documentos Office Open XML. Sugeriría usar DotNetZip o SharpZipLib
Si está manipulando archivos ZIP, es posible que desee buscar en una biblioteca de terceros para que lo ayude.
Por ejemplo, DotNetZip, que se ha actualizado recientemente. La versión actual ahora es v1.8. Aquí hay un ejemplo para crear un zip:
using (ZipFile zip = new ZipFile())
{
zip.AddFile("c://photos//personal//7440-N49th.png");
zip.AddFile("c://Desktop//2005_Annual_Report.pdf");
zip.AddFile("ReadMe.txt");
zip.Save("Archive.zip");
}
Aquí hay un ejemplo para actualizar un archivo zip existente; no necesita extraer los archivos para hacerlo:
using (ZipFile zip = ZipFile.Read("ExistingArchive.zip"))
{
// 1. remove an entry, given the name
zip.RemoveEntry("README.txt");
// 2. Update an existing entry, with content from the filesystem
zip.UpdateItem("Portfolio.doc");
// 3. modify the filename of an existing entry
// (rename it and move it to a sub directory)
ZipEntry e = zip["Table1.jpg"];
e.FileName = "images/Figure1.jpg";
// 4. insert or modify the comment on the zip archive
zip.Comment = "This zip archive was updated " + System.DateTime.ToString("G");
// 5. finally, save the modified archive
zip.Save();
}
aquí hay un ejemplo que extrae entradas:
using (ZipFile zip = ZipFile.Read("ExistingZipFile.zip"))
{
foreach (ZipEntry e in zip)
{
e.Extract(TargetDirectory, true); // true => overwrite existing files
}
}
DotNetZip admite caracteres multi-byte en nombres de archivos, encriptación Zip, encriptación AES, streams, Unicode, archivos autoextraíbles. También hace ZIP64, para longitudes de archivo mayores que 0xFFFFFFFF, o para archivos con más de 65535 entradas.
gratis. fuente abierta
conseguirlo en codeplex
Desde " Clase ZipPackage " (MSDN):
Mientras que los paquetes se almacenan como archivos Zip * a través de la clase ZipPackage, todos los archivos Zip no son ZipPackages. Un ZipPackage tiene requisitos especiales como nombres de archivos (parte) compatibles con URI y un archivo "[Content_Types] .xml" que define los tipos MIME para todos los archivos contenidos en el paquete. La clase ZipPackage no se puede usar para abrir archivos Zip arbitrarios que no cumplan con el estándar de Convenciones de empaquetado abierto.
Para obtener más información, consulte la Sección 9.2 "Asignación a un archivo comprimido ZIP" del estándar "Convenciones de empaquetado abierto" de ECMA International, http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML% 20Parte% 202% 20 (DOCX) .zip (342Kb) o http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML%20Part%202%20(PDF).zip (1.3Mb)
* Simplemente puede agregar ".zip" a la extensión de cualquier archivo ZipPackage (.docx, .xlsx, .pptx, etc.) para abrirlo en su utilidad Zip favorita.
¡Estaba teniendo exactamente el mismo problema! Para que el método GetParts () devuelva algo, tuve que agregar el archivo [Content_Types] .xml a la raíz del archivo con un nodo "Predeterminado" para cada extensión de archivo incluida. Una vez que agregué esto (solo usando Windows Explorer), mi código pudo leer y extraer los contenidos archivados.
Puede encontrar más información sobre el archivo [Content_Types] .xml aquí:
http://msdn.microsoft.com/en-us/magazine/cc163372.aspx : hay un archivo de ejemplo debajo de la figura 13 del artículo.
var zipFilePath = "c://myfile.zip";
var tempFolderPath = "c://unzipped";
using (Package package = ZipPackage.Open(zipFilePath, FileMode.Open, FileAccess.Read))
{
foreach (PackagePart part in package.GetParts())
{
var target = Path.GetFullPath(Path.Combine(tempFolderPath, part.Uri.OriginalString.TrimStart(''/'')));
var targetDir = target.Remove(target.LastIndexOf(''//'));
if (!Directory.Exists(targetDir))
Directory.CreateDirectory(targetDir);
using (Stream source = part.GetStream(FileMode.Open, FileAccess.Read))
{
FileStream targetFile = File.OpenWrite(target);
source.CopyTo(targetFile);
targetFile.Close();
}
}
}
Nota: este código usa el método Stream.CopyTo en .NET 4.0
(Esto es básicamente una reformulación de esta respuesta )
Resulta que System.IO.Packaging.ZipPackage
no admite PKZIP, es por eso que cuando se abre un archivo ZIP "genérico" no se devuelven "partes". Esta clase solo admite algunos sabores específicos de archivos ZIP (consulte los comentarios en la parte inferior de la descripción de MSDN ) utilizados entre otros como paquetes de servicio de Windows Azure hasta SDK 1.6. Por eso, si descomprime un paquete de servicio y lo vuelve a empaquetar usando diga Info-ZIP empacador se convertirá en inválido.