使用System.IO.Compression创建的zip文件无效
本文关键字:zip 文件 无效 创建 System IO Compression 使用 | 更新日期: 2023-09-27 18:14:06
我正在尝试创建一个包含一个或多个文件的zip文件。
我使用的是。net framework 4.5,更具体地说是System.IO.Compression命名空间。
目标是允许用户通过ASP下载zip文件。. NET MVC应用程序。
zip文件正在生成并发送到客户端,但当我试图通过双击打开它时,我得到以下错误:
Windows无法打开该文件夹。压缩的文件夹…无效。
下面是我的代码:
[HttpGet]
public FileResult Download()
{
var fileOne = CreateFile(VegieType.POTATO);
var fileTwo = CreateFile(VegieType.ONION);
var fileThree = CreateFile(VegieType.CARROT);
IEnumerable<FileContentResult> files = new List<FileContentResult>() { fileOne, fileTwo, fileThree };
var zip = CreateZip(files);
return zip;
}
private FileContentResult CreateFile(VegieType vType)
{
string fileName = string.Empty;
string fileContent = string.Empty;
switch (vType)
{
case VegieType.BATATA:
fileName = "batata.csv";
fileContent = "THIS,IS,A,POTATO";
break;
case VegieType.CEBOLA:
fileName = "cebola.csv";
fileContent = "THIS,IS,AN,ONION";
break;
case VegieType.CENOURA:
fileName = "cenoura.csv";
fileContent = "THIS,IS,A,CARROT";
break;
default:
break;
}
var fileBytes = Encoding.GetEncoding(1252).GetBytes(fileContent);
return File(fileBytes, MediaTypeNames.Application.Octet, fileName);
}
private FileResult CreateZip(IEnumerable<FileContentResult> files)
{
byte[] retVal = null;
if (files.Any())
{
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false))
{
foreach (var f in files)
{
var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
entryStream.Write(f.FileContents, 0, f.FileContents.Length);
entryStream.Close();
}
}
zipStream.Position = 0;
retVal = zipStream.ToArray();
}
}
}
return File(retVal, MediaTypeNames.Application.Zip, "horta.zip");
}
有没有人能解释一下为什么当我双击我的zip文件时,windows说我的zip文件无效。
最后考虑一下,我可以使用7-Zip打开它。
您需要在ZipArchive对象被处置后通过ToArray获得MemoryStream缓冲区。否则你最终会得到损坏的存档。
请注意,我已经改变了ZipArchive构造函数的参数,以便在添加条目时保持打开状态。
当ZipArchive被处理时,有一些校验和正在进行,所以如果你之前读MemoryStream,它仍然是不完整的。
private FileResult CreateZip(IEnumerable<FileContentResult> files)
{
byte[] retVal = null;
if (files.Any())
{
using (MemoryStream zipStream = new MemoryStream())
{
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
{
foreach (var f in files)
{
var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest);
using (BinaryWriter writer = new BinaryWriter(entry.Open()))
{
writer.Write(f.FileContents, 0, f.FileContents.Length);
writer.Close();
}
}
zipStream.Position = 0;
}
retVal = zipStream.ToArray();
}
}
return File(retVal, MediaTypeNames.Application.Zip, "horta.zip");
}
直接返回流…
private ActionResult CreateZip(IEnumerable files)
{
if (files.Any())
{
MemoryStream zipStream = new MemoryStream();
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false))
{
foreach (var f in files)
{
var entry = archive.CreateEntry(f.FileDownloadName, CompressionLevel.Fastest);
using (var entryStream = entry.Open())
{
entryStream.Write(f.FileContents, 0, f.FileContents.Length);
entryStream.Close();
}
}
}
zipStream.Position = 0;
return File(zipStream, MediaTypeNames.Application.Zip, "horta.zip");
}
return new EmptyResult();
}
尝试更改
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, false))
using (ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
在这种用法中,归档文件在流关闭时被强制写入流。但是,如果构造函数的leaveOpen参数被设置为false,它也会关闭底层流。
当我为条目添加错误的名称时,如示例
var fileToZip = "/abc.txt";
ZipArchiveEntry zipFileEntry = zipArchive.CreateEntry(fileToZip);
我得到了同样的错误。修改文件名后,现在可以了
我得到了"压缩(压缩)文件夹…是无效的!"错误,因为我的条目以"/"开头命名在他们面前。一些zip解压程序在这方面没有问题,但是Windows的那个有问题。我通过从条目名称(从"/file.txt")中删除斜杠来解决这个问题。以"file.txt"。