it-swarm.com.de

Wie kann ich eine Datei in C # komprimieren, ohne Drittanbieter-APIs?

Ich bin mir ziemlich sicher, dass dies kein Duplikat ist, also bleib nur eine Minute bei mir.

Wie kann ich programmgesteuert (C #) eine Datei (in Windows) komprimieren, ohne Bibliotheken von Drittanbietern zu verwenden? Ich brauche einen nativen Windows-Aufruf oder ähnliches. Ich mag die Idee, einen Prozess zu starten, wirklich nicht, aber ich werde es tun, wenn ich es unbedingt muss. Ein Anruf von Pinovke wäre viel besser.

Wenn dies nicht der Fall ist, möchte ich Ihnen sagen, was ich wirklich erreichen möchte: Ich brauche die Möglichkeit, dass ein Benutzer eine Sammlung von Dokumenten in einer einzigen Anforderung herunterladen kann. Irgendwelche Ideen, wie man das erreichen kann?

150
Esteban Araya

Verwenden Sie .NET 3.5? Sie können die Klasse ZipPackage und verwandte Klassen verwenden. Es ist mehr als nur das Zippen einer Dateiliste, da für jede hinzugefügte Datei ein MIME-Typ gewünscht wird. Es könnte tun, was Sie wollen.

Ich verwende diese Klassen derzeit für ein ähnliches Problem, um mehrere verwandte Dateien in einer einzigen Datei zum Download zu archivieren. Wir verwenden eine Dateierweiterung, um die Download-Datei unserer Desktop-App zuzuordnen. Ein kleines Problem, bei dem wir aufkamen, war, dass es nicht möglich ist, ein Drittanbieter-Tool wie 7-Zip zu verwenden, um die Zip-Dateien zu erstellen, da der clientseitige Code sie nicht öffnen kann. ZipPackage fügt eine versteckte Datei hinzu, die den Inhaltstyp beschreibt jede Komponentendatei und kann keine Zip-Datei öffnen, wenn diese Inhaltstypendatei fehlt.

83
Brian Ensink

Wie kann ich programmgesteuert (C #) eine Datei (in Windows) komprimieren, ohne .__ zu verwenden. Bibliotheken von Drittanbietern?

Wenn Sie das 4.5+ Framework verwenden, gibt es jetzt die Klassen ZipArchive und ZipFile .

using (ZipArchive Zip = ZipFile.Open("test.Zip", ZipArchiveMode.Create))
{
    Zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt");
}

Sie müssen Verweise hinzufügen auf:

  • System.IO.Compression
  • System.IO.Compression.FileSystem

Für das .NET Core-Targeting-net46 müssen Sie Abhängigkeiten für hinzufügen 

  • System.IO.Compression 
  • System.IO.Compression.ZipFile

Beispiel project.json:

"dependencies": {
  "System.IO.Compression": "4.1.0",
  "System.IO.Compression.ZipFile": "4.0.1"
},

"frameworks": {
  "net46": {}
}

Für .NET Core 2.0 genügt es, eine einfache using-Anweisung hinzuzufügen:

  • using System.IO.Compression;
256
GalacticJello

Ich befand mich in der gleichen Situation und wollte .NET anstelle einer Drittanbieter-Bibliothek. Als ein anderes Poster, das oben erwähnt wurde, reicht es nicht aus, einfach die in .NET 3.5 eingeführte ZipPackage-Klasse zu verwenden. Es gibt eine zusätzliche Datei, die im Archiv enthalten sein MUSS, damit das ZipPackage funktioniert. Wenn diese Datei hinzugefügt wird, kann das resultierende Zip-Paket direkt vom Windows Explorer aus geöffnet werden - kein Problem.

Alles, was Sie tun müssen, ist, die [Content_Types] .xml-Datei mit einem "Default" -Knoten für jede Dateierweiterung, die Sie hinzufügen möchten, zum Stamm des Archivs hinzuzufügen. Nach dem Hinzufügen könnte ich das Paket von Windows Explorer aus durchsuchen oder den Inhalt programmgesteuert dekomprimieren und lesen.

Weitere Informationen zur Datei [Content_Types] .xml finden Sie hier: http://msdn.Microsoft.com/en-us/magazine/cc163372.aspx

Hier ist ein Beispiel für die Datei [Content_Types] .xml (muss genau benannt werden):

<?xml version="1.0" encoding="utf-8" ?>
<Types xmlns=
    "http://schemas.openxmlformats.org/package/2006/content-types">
  <Default Extension="xml" ContentType="text/xml" /> 
  <Default Extension="htm" ContentType="text/html" /> 
  <Default Extension="html" ContentType="text/html" /> 
  <Default Extension="rels" ContentType=
    "application/vnd.openxmlformats-package.relationships+xml" /> 
  <Default Extension="jpg" ContentType="image/jpeg" /> 
  <Default Extension="png" ContentType="image/png" /> 
  <Default Extension="css" ContentType="text/css" /> 
</Types>

Und das C # zum Erstellen einer Zip-Datei:

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)) 
            { 
                source.CopyTo(File.OpenWrite(target)); 
            } 
        } 
    } 

Hinweis: 

11
Joshua
    private static string CompressFile(string sourceFileName)
    {
        using (ZipArchive archive = ZipFile.Open(Path.ChangeExtension(sourceFileName, ".Zip"), ZipArchiveMode.Create))
        {
            archive.CreateEntryFromFile(sourceFileName, Path.GetFileName(sourceFileName));
        }
        return Path.ChangeExtension(sourceFileName, ".Zip");
    }
5
FLICKER

Für eine .NET 2.0-App habe ich SharpZipLib verwendet. Einfach zu bedienen und Open Source. 

4
Tim Scarborough

Basierend auf der Antwort von Simon McKenzie auf diese Frage würde ich vorschlagen, ein paar Methoden wie diese zu verwenden:

    public static void ZipFolder(string sourceFolder, string zipFile)
    {
        if (!System.IO.Directory.Exists(sourceFolder))
            throw new ArgumentException("sourceDirectory");

        byte[] zipHeader = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };

        using (System.IO.FileStream fs = System.IO.File.Create(zipFile))
        {
            fs.Write(zipHeader, 0, zipHeader.Length);
        }

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic source = shellApplication.NameSpace(sourceFolder);
        dynamic destination = shellApplication.NameSpace(zipFile);

        destination.CopyHere(source.Items(), 20);
    }

    public static void UnzipFile(string zipFile, string targetFolder)
    {
        if (!System.IO.Directory.Exists(targetFolder))
            System.IO.Directory.CreateDirectory(targetFolder);

        dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
        dynamic compressedFolderContents = shellApplication.NameSpace(zipFile).Items;
        dynamic destinationFolder = shellApplication.NameSpace(targetFolder);

        destinationFolder.CopyHere(compressedFolderContents);
    }
}
1
mccdyl001

Sieht so aus, als könnten Sie Windows einfach so machen - dies ...

Leider glaube ich nicht, dass Sie einen separaten Prozess starten können, wenn Sie nicht zu einer Komponente eines Drittanbieters wechseln. 

0
Dave Swersky

Fügen Sie Ihrem Projekt diese 4 Funktionen hinzu:

        public const long BUFFER_SIZE = 4096;
    public static void AddFileToZip(string zipFilename, string fileToAdd)
    {
        using (Package Zip = global::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);
                }
            }
        }
    }
    public static void CopyStream(global::System.IO.FileStream inputStream, global::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;
        }
    }
    public static void RemoveFileFromZip(string zipFilename, string fileToRemove)
    {
        using (Package Zip = global::System.IO.Packaging.Package.Open(zipFilename, FileMode.OpenOrCreate))
        {
            string destFilename = ".\\" + fileToRemove;
            Uri uri = PackUriHelper.CreatePartUri(new Uri(destFilename, UriKind.Relative));
            if (Zip.PartExists(uri))
            {
                Zip.DeletePart(uri);
            }
        }
    }
    public static void Remove_Content_Types_FromZip(string zipFileName)
    {
        string contents;
        using (ZipFile zipFile = new ZipFile(File.Open(zipFileName, FileMode.Open)))
        {
            /*
            ZipEntry startPartEntry = zipFile.GetEntry("[Content_Types].xml");
            using (StreamReader reader = new StreamReader(zipFile.GetInputStream(startPartEntry)))
            {
                contents = reader.ReadToEnd();
            }
            XElement contentTypes = XElement.Parse(contents);
            XNamespace xs = contentTypes.GetDefaultNamespace();
            XElement newDefExt = new XElement(xs + "Default", new XAttribute("Extension", "sab"), new XAttribute("ContentType", @"application/binary; modeler=Acis; version=18.0.2application/binary; modeler=Acis; version=18.0.2"));
            contentTypes.Add(newDefExt);
            contentTypes.Save("[Content_Types].xml");
            zipFile.BeginUpdate();
            zipFile.Add("[Content_Types].xml");
            zipFile.CommitUpdate();
            File.Delete("[Content_Types].xml");
            */
            zipFile.BeginUpdate();
            try
            {
                zipFile.Delete("[Content_Types].xml");
                zipFile.CommitUpdate();
            }
            catch{}
        }
    }

Und benutze sie so:

foreach (string f in UnitZipList)
{
    AddFileToZip(zipFile, f);
    System.IO.File.Delete(f);
}
Remove_Content_Types_FromZip(zipFile);
0
Teemo