C# 从字节[]创建zip文件
我试图在.NET4.5(System.IO.Compression)中从一系列字节数组创建一个Zip文件。例如,从我正在使用的API中,我得到了一个C# 从字节[]创建zip文件,c#,.net,asp.net-mvc,zip,.net-4.5,C#,.net,Asp.net Mvc,Zip,.net 4.5,我试图在.NET4.5(System.IO.Compression)中从一系列字节数组创建一个Zip文件。例如,从我正在使用的API中,我得到了一个列表,每个附件都有一个名为Body的属性,它是一个字节[]。如何迭代该列表并创建包含每个附件的zip文件 现在我的印象是,我必须将每个附件写入磁盘,并从中创建zip文件 //This is great if I had the files on disk ZipFile.CreateFromDirectory(startPath, zipPath);
列表
,每个附件
都有一个名为Body
的属性,它是一个字节[]
。如何迭代该列表并创建包含每个附件的zip文件
现在我的印象是,我必须将每个附件写入磁盘,并从中创建zip文件
//This is great if I had the files on disk
ZipFile.CreateFromDirectory(startPath, zipPath);
//How can I create it from a series of byte arrays?
GZipStream和deflatesttream似乎可以让您使用streams/byte数组来解决问题,但大多数用户可能无法使用压缩文件格式。(即,您的文件将具有.gz扩展名)如果此文件仅在内部使用,则可以 我不知道如何使用Microsoft的库制作ZIP,但我记得这个库支持您可能会发现有用的东西:
它是在LGPL下授权的。经过一段时间的游戏和阅读,我终于明白了这一点。以下是如何创建包含多个文件的zip文件(存档),而无需将任何临时数据写入磁盘:
using (var compressedFileStream = new MemoryStream())
{
//Create an archive and store the stream in memory.
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false)) {
foreach (var caseAttachmentModel in caseAttachmentModels) {
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body))
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
}
return new FileContentResult(compressedFileStream.ToArray(), "application/zip") { FileDownloadName = "Filename.zip" };
}
这是OP发布的公认答案的变体。然而,这是针对WebForms而不是MVC的。我假设caseAttachmentModel.Body是一个字节[] 本质上,除了一个额外的方法将zip作为响应发送出去外,其他一切都是一样的
using (var compressedFileStream = new MemoryStream()) {
//Create an archive and store the stream in memory.
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false)) {
foreach (var caseAttachmentModel in caseAttachmentModels) {
//Create a zip entry for each attachment
var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);
//Get the stream of the attachment
using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body)) {
using (var zipEntryStream = zipEntry.Open()) {
//Copy the attachment stream to the zip entry stream
originalFileStream.CopyTo(zipEntryStream);
}
}
}
}
sendOutZIP(compressedFileStream.ToArray(), "FileName.zip");
}
private void sendOutZIP(byte[] zippedFiles, string filename)
{
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/x-compressed";
Response.Charset = string.Empty;
Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
Response.BinaryWrite(zippedFiles);
Response.OutputStream.Flush();
Response.OutputStream.Close();
Response.End();
}
我还想指出,@Levi Fuller在被接受的答案中给出的关于推荐人的建议是正确的 您是否查看了中的其他类,特别是那些名称中包含Stream的类@AustinSalonen-我可能遗漏了一些东西,但是,我不认为我可以将多个文件作为GZipStream的输出。我需要的最终结果是多个我不相信GZipStream支持的文件。好的,然后尝试SevenZipSharp。它是围绕7-zip库构建的,但也可以压缩为.zip文件。Codeplex上也可能有类似的库。友好提示-如果ZipArchive类不可用,请添加对程序集的引用:右键单击
引用
->添加引用
。在Assemblies
下,搜索System.IO
并勾选System.IO.Compression.FileSystem
和System.IO.Compression
。什么是caseAttachmentModels?字节[]在哪里?我使用了这个,但是“compressedFileStream”的长度始终为0。。。有什么想法吗?@krillgar你的编辑引入了一个bug。在关闭zipArchive
后,原始文件具有return语句。通过删除嵌套,您现在还可以在zipArchive
using
语句中使用return语句。如果不进行处理,则档案无效。@Zeph是正确的。我必须在原始using语句周围添加大括号,并将return语句移出一级以使我的zipArchive有效。我们可以将密码设置为zip文件吗?System.IO.Compression.zipArchive()的文档中没有显示任何为zip文件设置密码的选项。根据这个(旧的)线程()的说法,.NET文件中没有密码功能,建议寻找第三方库。