Problem
Please bear with me for a moment as I double-check that this isn’t a duplicate.
How can I ZIP a file (in Windows) programmatically (in C#) without utilizing any third-party libraries? I’m looking for a native Windows call or something similar; I despise the notion of starting a process, but I’ll do it if I have to. It would be much preferable to make a PInovke call.
If that fails, let me tell you what I’m truly trying to do: I require the ability to allow a user to download a group of documents in one request. Do you have any suggestions about how to go about doing this?
Asked by Esteban Araya
Solution #1
The ZipArchive and ZipFile classes are now available in the 4.5+ Framework.
using (ZipArchive zip = ZipFile.Open("test.zip", ZipArchiveMode.Create))
{
zip.CreateEntryFromFile(@"c:\something.txt", "data/path/something.txt");
}
You must include citations to the following sources:
You must include dependencies for net46 when using.NET Core.
Example project.json:
"dependencies": {
"System.IO.Compression": "4.1.0",
"System.IO.Compression.ZipFile": "4.0.1"
},
"frameworks": {
"net46": {}
}
All that is required for.NET Core 2.0 is the addition of a simple using statement:
Answered by GalacticJello
Solution #2
Do you have.NET 3.5 installed? The ZipPackage class and associated classes could be used. It requires a MIME type for each file you add, so it’s more than just zipping up a file list. It might be able to fulfill your requirements.
I’m now using these classes to archive numerous linked files into a single file for download, which is a similar situation. To link the download file to our desktop app, we employ a file extension. One minor issue we encountered was that using a third-party tool like 7-zip to build the zip files was not possible since the client side code couldn’t open them — ZipPackage inserts a hidden file defining the content type of each component file and can’t read a zip file if that file is absent.
Answered by Brian Ensink
Solution #3
I was in the same boat, preferring to use.NET over a third-party library. As indicated by another poster, merely utilizing the ZipPackage class (added in.NET 3.5) is insufficient. In order for the ZipPackage to work, an additional file must be included in the archive. If this file is included, the resulting ZIP package can be opened without difficulty using Windows Explorer.
All you have to do is place a “Default” node for each file extension you want to include in the [Content Types].xml file at the root of the archive. I could view the package from Windows Explorer or decompress and read its contents programmatically after it was added.
Here’s where you may learn more about the [Content Types].xml file: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx
The [Content Types].xml (must be named exactly) file looks like this:
<?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>
And here’s how to make a ZIP file with C#:
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));
}
}
}
Note:
Answered by Joshua
Solution #4
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");
}
Answered by FLICKER
Solution #5
I’d recommend employing a pair of methods based on Simon McKenzie’s response to this question:
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);
}
}
Answered by mccdyl001
Post is based on https://stackoverflow.com/questions/940582/how-do-i-zip-a-file-in-c-using-no-3rd-party-apis