使用 System.IO.Compression 创建 zip 文件后无效
Invalid zip file after creating it with System.IO.Compression
我正在尝试创建一个包含一个或多个文件的 zip 文件。
我使用的是 .NET Framework 4.5,更具体地说是 System.IO.Compression 命名空间。
objective 允许用户通过 ASP.NET MVC 应用程序下载 zip 文件。
正在生成 zip 文件并将其发送到客户端,但是当我尝试通过双击打开它时,出现以下错误:
Windows 无法打开文件夹。
压缩(zipped)文件夹...无效。
这是我的代码:
[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");
}
谁能解释一下为什么 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");
}
只是 return 流...
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 文件。
我使用的是 .NET Framework 4.5,更具体地说是 System.IO.Compression 命名空间。
objective 允许用户通过 ASP.NET MVC 应用程序下载 zip 文件。
正在生成 zip 文件并将其发送到客户端,但是当我尝试通过双击打开它时,出现以下错误:
Windows 无法打开文件夹。
压缩(zipped)文件夹...无效。
这是我的代码:
[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");
}
谁能解释一下为什么 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");
}
只是 return 流...
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);
我遇到了同样的错误。修改文件名后就可以了