提问人:Reza Akraminejad 提问时间:5/4/2016 最后编辑:McMillan ChengReza Akraminejad 更新时间:3/23/2023 访问量:65530
使用密码在.NET中创建zip文件
create zip file in .net with password
问:
我正在处理一个项目,我需要创建一个 zip 文件,密码受 c# 中文件内容的影响。
在我使用 System.IO.Compression.GZipStream 创建 gzip 内容之前。 .net 是否有任何功能来创建受 zip 或 rar 密码保护的文件?
答:
8赞
Manfred Radlwimmer
5/4/2016
#1
不幸的是,框架中没有这样的功能。有一种方法可以制作ZIP文件,但没有密码。如果你想在C#中创建受密码保护的ZIP文件,我推荐SevenZipSharp。它基本上是 7-Zip 的托管包装器。
SevenZipBase.SetLibraryPath(Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? Environment.CurrentDirectory,
"7za.dll"));
SevenZipCompressor compressor = new SevenZipCompressor();
compressor.Compressing += Compressor_Compressing;
compressor.FileCompressionStarted += Compressor_FileCompressionStarted;
compressor.CompressionFinished += Compressor_CompressionFinished;
string password = @"whatever";
string destinationFile = @"C:\Temp\whatever.zip";
string[] sourceFiles = Directory.GetFiles(@"C:\Temp\YourFiles\");
if (String.IsNullOrWhiteSpace(password))
{
compressor.CompressFiles(destinationFile, sourceFiles);
}
else
{
//optional
compressor.EncryptHeaders = true;
compressor.CompressFilesEncrypted(destinationFile, password, sourceFiles);
}
评论
0赞
frankhommers
9/4/2019
不幸的是,这个解决方案只是Windows,因为它依赖于7za.dll。其他解决方案跨平台工作。
15赞
Jan Wiesemann
5/4/2016
#2
看看 DotNetZip(@AFract在评论中提供了指向 GitHub 的新链接)
它有相当多的文档,它还允许您在运行时将 dll 加载为嵌入文件。
评论
0赞
Paul
7/10/2018
我已经下载了这个,但在下载中找不到要在我的项目中使用的 DLL。
0赞
StayOnTarget
8/8/2018
这还在维护吗?原始项目有一个 github 分支,但自从 CodePlex 关闭以来,我经常不确定此类项目的状态
2赞
Jan Wiesemann
8/9/2018
nuget.org/packages/DotNetZip“3个月前的最后更新”我认为它仍然保持。
0赞
AFract
1/27/2020
绑定到 nuget 包的 github 存储库: github.com/haf/DotNetZip.Semverd 不要看 codeplex,它(显然)已经过时了,因为 Codeplex 已经死了。
0赞
Demodave
5/1/2020
请举例说明
5赞
testing
7/18/2018
#3
我想添加更多替代方案。
对于 .NET,可以使用 SharpZipLib,对于 Xamarin,可以使用 SharpZipLib.Portable。
.NET 示例:
using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
zipStream.Password = "Your password";
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
更多示例可以在这里找到。
如果您可以不使用密码功能,则可以提及 ZipStorer 或 System.IO.Compression
中的内置 .NET 函数。
6赞
LCJ
12/15/2020
#4
DotNetZip 以干净的方式运行良好。
DotNetZip is a FAST, FREE class library and toolset for manipulating zip files.
法典
static void Main(string[] args)
{
using (ZipFile zip = new ZipFile())
{
zip.Password = "mypassword";
zip.AddDirectory(@"C:\Test\Report_CCLF5\");
zip.Save(@"C:\Test\Report_CCLF5_PartB.zip");
}
}
评论
0赞
Paul Efford
3/15/2023
它创建了一个 zip,您可以在其中查看其中的文件;要打开其中任何一个,您将被要求输入密码。有趣的是,您可以提取zip并获取其中的所有文件......无需输入任何密码!所以。。。这个“密码”功能的真正用例是什么?
0赞
Paul Efford
3/23/2023
#5
我发现有两个选项是可靠且易于使用的,具体取决于允许您在项目中使用的许可证类型。
第一个是:
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
namespace DataReader.zip
{
internal static class Zip1 // SharpZipLib nuget lib, MIT free license
{
public static bool Create(string destZipPath, string folderToCompress, string? password = null, int compressionLevel = 3)
{
bool res;
try
{
var fsOut = File.Create($"{destZipPath}.zip"); // ending '.zip' is a must!
var zipStream = new ZipOutputStream(fsOut);
zipStream.SetLevel(compressionLevel); // 0-9, 9 being the highest level of compression
zipStream.Password = password; // optional. Null is the same as not setting. Required if using AES.
// This setting will strip the leading part of the folder path in the entries, to
// make the entries relative to the starting folder.
// To include the full path for each entry up to the drive root, assign folderOffset = 0.
var folderOffset = folderToCompress.Length + (folderToCompress.EndsWith("\\") ? 0 : 1);
res = CompressFolder(folderToCompress, zipStream, folderOffset);
zipStream.IsStreamOwner = true; // Makes the Close also Close the underlying stream
zipStream.Close();
return res;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
private static bool CompressFolder(string path, ZipOutputStream zipStream, int folderOffset)
{
try
{
var files = Directory.GetFiles(path);
if (files.Length == 0)
{
Message.Show($"Warning: no files to compress found in folder '{path}'");
return false;
}
foreach (var filename in files)
{
var fi = new FileInfo(filename);
var entryName = filename.Substring(folderOffset); // Makes the name in zip based on the folder
entryName = ZipEntry.CleanName(entryName); // Removes drive from name and fixes slash direction
var newEntry = new ZipEntry(entryName);
newEntry.DateTime = fi.LastWriteTime; // Note the zip format stores 2 second granularity
// Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
// A password on the ZipOutputStream is required if using AES.
// newEntry.AESKeySize = 256;
// To permit the zip to be unpacked by built-in extractor in WinXP and Server2003, WinZip 8, Java, and other older code,
// you need to do one of the following: Specify UseZip64.Off, or set the Size.
// If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility, you do not need either,
// but the zip will be in Zip64 format which not all utilities can understand.
zipStream.UseZip64 = UseZip64.On;
newEntry.Size = fi.Length;
zipStream.PutNextEntry(newEntry);
// Zip the file in buffered chunks
// the "using" will close the stream even if an exception occurs
var buffer = new byte[4096];
using (var streamReader = File.OpenRead(filename))
{
StreamUtils.Copy(streamReader, zipStream, buffer);
}
zipStream.CloseEntry();
}
return true;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
}
}
第二个:
using Ionic.Zip;
namespace DataReader.zip
{
internal class Zip2 // DotNetZip nuget lib
{
public static bool Create(string destZipPath, string folderToCompress, string? password = null, int compressionLevel = 3)
{
try
{
using ZipFile zip = new();
if (password != null)
zip.Password = password;
zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)compressionLevel;
zip.AddDirectory(folderToCompress);
zip.Save($"{destZipPath}.zip");
return true;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
}
}
使用这两个选项,您将创建一个 zip 文件夹,其中将需要密码来提取文件(如果您在调用该方法时设置了它)。
评论
GZipStream
DeflateStream
ZipPackage
ZipFile