Estrazione di file da un archivio Zip a livello di codice utilizzando C# e System.IO.Packaging

StackOverflow https://stackoverflow.com/questions/507751

  •  21-08-2019
  •  | 
  •  

Domanda

Ho un sacco di file ZIP che hanno un disperato bisogno di una riorganizzazione ed estrazione gerarchica.Quello che posso fare, al momento, è creare la struttura delle directory e spostare i file zip nella posizione corretta.Il formaggio mistico che mi manca è la parte che estrae i file dall'archivio ZIP.

Ho visto gli articoli MSDN su ZipArchive classe e comprenderli ragionevolmente bene.Ho visto anche il Modi di estrazione VBScript.Questa non è una classe complessa, quindi estrarre materiale dovrebbe essere piuttosto semplice.In effetti, funziona "per lo più".Ho incluso il mio codice attuale di seguito come riferimento.

 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.
    }
 }

Il problema sembra essere da qualche parte nel GetParts (o OttieniNulla per questo motivo).Sembra che il pacco, mentre è aperto, sia vuoto.Scavando più a fondo il debugger mostra che il membro privato _zipArchive mostra che in realtà ha parti.Parti con i nomi giusti e tutto il resto.Perché il GetParts funzione recuperarli?Ho provato ad aprire un ZipArchive e questo non ha aiutato.Grr.

È stato utile?

Soluzione

Se stai manipolando file ZIP, potresti voler esaminare una libreria di terze parti per aiutarti.

Ad esempio, DotNetZip, che è stato recentemente aggiornato.La versione attuale è ora v1.8.Ecco un esempio per creare 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");
}

Ecco un esempio per aggiornamento un zip esistente;non è necessario estrarre i file per farlo:

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

ecco un esempio che estrae le voci:

using (ZipFile zip = ZipFile.Read("ExistingZipFile.zip"))
{
  foreach (ZipEntry e in zip)
  {
    e.Extract(TargetDirectory, true);  // true => overwrite existing files
  }
}

DotNetZip supporta caratteri multibyte nei nomi di file, crittografia Zip, crittografia AES, flussi, Unicode, archivi autoestraenti.Funziona anche con ZIP64, per file di lunghezza maggiore di 0xFFFFFFFF o per archivi con più di 65535 voci.

gratuito.fonte aperta

prendilocodeplex O download diretto da windows.net - CodePlex è stato interrotto e archiviato

Altri suggerimenti

MSDN ,

In questo esempio, la classe pacchetto viene utilizzata (in contrapposizione al ZipPackage.) Avendo lavorato con entrambi, ho visto solo flakiness accadere quando c'è la corruzione nel file zip. Non necessariamente la corruzione che genera l'estrattore di Windows o Winzip, ma qualcosa che i componenti dell'imballaggio devono gestire problemi.

Spero che questo aiuti, forse è in grado di fornire un'alternativa al debug 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();
    }
}

Da " ZipPackage Classe "(MSDN):

  

Mentre i pacchetti vengono memorizzati come file Zip * attraverso la classe ZipPackage, tutti i file Zip non sono ZipPackages. Uno ZipPackage ha esigenze speciali, come file di URI-compliant nomi (parte) e un file "[CONTENT_TYPES] .xml" che definisce i tipi MIME per tutti i file contenuti nel pacchetto. La classe ZipPackage non può essere utilizzato per aprire file Zip arbitrari che non sono conformi alla Open standard di imballaggio convenzioni.

     

Per ulteriori dettagli vedere paragrafo 9.2 "Mappatura ad un archivio ZIP" dello standard ECMA Internazionale "di Open Packaging Conventions", http://www.ecma-international.org/publications/files/ECMA-ST/Office%20Open%20XML % 20Part% 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)

     

* Si può semplicemente aggiungere ".zip" per l'estensione di qualsiasi file ZipPackage-based (.docx, .xlsx, .pptx, etc.) per aprirlo nel vostro programma di utilità Zip preferito.

ho avuto lo stesso identico problema! Per ottenere i GetParts () metodo per restituire qualcosa, ho dovuto aggiungere il [CONTENT_TYPES] .xml alla radice l'archivio con un nodo "Default" per ogni estensione del file incluso. Una volta ho aggiunto questo (solo utilizzando Windows Explorer), il mio codice è stato in grado di leggere ed estrarre il contenuto archiviati.

Maggiori informazioni sul file XML [CONTENT_TYPES] può essere trovato qui:

http://msdn.microsoft.com/en-us/magazine/ cc163372.aspx -. C'è un esempio di file di seguito Figura 13 dell'articolo

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: questo codice utilizza il metodo Stream.CopyTo in .NET 4.0

Sono d'accordo withe Cheeso. System.IO.Packaging è imbarazzante durante la manipolazione dei file zip generici, visto che è stato progettato per Office Open XML. Io suggerirei di utilizzare DotNetZip o SharpZipLib

(Questo è fondamentalmente un riformulazione di questa risposta )

Risulta che System.IO.Packaging.ZipPackage non supporta PKZIP, è per questo che quando si apre un file ZIP "generico" no "parti" vengono restituiti. Questa classe supporta solo un certo sapore specifico di file ZIP (vedi commenti in fondo a descrizione MSDN ) utilizzato tra l'altro come pacchetti di servizi di Windows Azure SDK fino a 1.6 - è per questo che se si decomprime un pacchetto di servizi e richiuderla utilizzando dire Info-ZIP Packer diventerà valido.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top