![](/img/trans.png)
[英]Creating a ZIP archive in memory using System.IO.Compression
[英]Invalid zip file after creating it with System.IO.Compression
我正在嘗試創建一個包含一個或多個文件的zip文件。
我正在使用.NET framework 4.5,更具體地說是System.IO.Compression命名空間。
目標是允許用戶通過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");
}
只需返回流...
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);
我得到了同樣的錯誤。 在更正文件名后,現在沒問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.