如何在 C # 中压缩文件,不使用第三方 API?

我很确定这不是复制品,所以请稍等一下。

如何在不使用任何第三方库的情况下通过编程(C #) ZIP 文件(在 Windows 中) ?我需要一个本地窗口调用或类似的东西; 我真的不喜欢启动一个进程的想法,但如果必须这样做,我会这样做。皮诺夫克电话会更好。

如果做不到这一点,让我来告诉您我真正想要实现的是什么: 我需要能够让用户在单个请求中下载一组文档。有什么办法吗?

211887 次浏览

你在吸毒吗。NET 3.5?您可以使用 ZipPackage类和相关类。它不仅仅是压缩文件列表,因为它需要为您添加的每个文件提供 MIME 类型。也许能达到你的目的。

我目前正在使用这些类解决类似的问题,将几个相关文件归档到一个文件中以供下载。我们使用文件扩展名将下载文件与桌面应用程序关联。我们遇到的一个小问题是,不可能仅仅使用第三方工具如7-zip 来创建压缩文件,因为客户端代码无法打开它—— ZipPackage 添加了一个隐藏文件,描述每个组件文件的内容类型,如果内容类型文件丢失,则无法打开压缩文件。

看起来 Windows 可能会让你做 这个..。

不幸的是,我认为除非您转向第三方组件,否则无法启动一个单独的流程。

我当时也处在同样的境地,想要。NET 而不是第三方库。正如上面提到的另一张海报,只需使用 ZipPackage 类(在。NET 3.5)是不够的。为了使 ZipPackage 工作,必须在归档文件中包含一个附加文件。如果添加了这个文件,那么生成的压缩包可以直接从文件资源管理器打开——没有问题。

您所要做的就是添加[ Content _ Types ]。将 xml 文件放到归档文件的根目录,并为希望包含的每个文件扩展名设置“ Default”节点。一旦添加,我就可以通过文件资源管理器浏览软件包,或者通过编程方式解压并阅读其内容。

有关[ Content _ Types ] . xml 文件的更多信息可以在这里找到: http://msdn.microsoft.com/en-us/magazine/cc163372.aspx

下面是[ Content _ Types ] . xml (必须准确命名)文件的一个示例:

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

以及用于创建 ZIP 文件的 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));
}
}
}

注:

< p > 如何以编程方式(C #) ZIP 文件(在 Windows 中)而不使用 任何第三方图书馆

如果使用4.5 + 框架,现在就有了 ZipArchiveZipFile类。

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

您需要添加以下参考文献:

  • 系统,内窥镜,压缩
  • System.IO.Compression.FileSystem

对于针对 net46的.NETCore,您需要为

  • 系统,内窥镜,压缩
  • System.IO.Compression.ZipFile

例子 project.json:

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


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

对于.NET Core 2.0,只需要添加一个简单的 using 语句:

  • 使用 System.IO.Compress;

基于 Simon McKenzie 的答案 回答这个问题,我建议使用这样的一对方法:

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

将以下4个函数添加到项目中:

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

像这样使用它们:

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

现在在 dotnet 文档中有一个关于如何在没有第三方库的情况下压缩和解压缩的官方文档部分。它还包括完整的代码示例!

https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-compress-and-extract-files