簡體   English   中英

打開使用EPPlus創建的.xlsx文件並使用ICSharpCode.SharpZipLib壓縮到一個文件夾時出現問題

[英]Problems opening .xlsx file created with EPPlus and zipped in a folder with ICSharpCode.SharpZipLib

我正在使用EPPlus創建ExcelPackages(xlsx文檔)列表,並將它們作為ZipEntries添加到ZipOutputStream。 我認為Excel文檔應該是有效的,因為當我將其中一個文件寫入Response對象而不進行壓縮時,我可以正常打開它們。
zip文件夾是按預期創建的,文件在那里並且似乎沒有空,但是當我嘗試打開它們時,我在Excel中收到以下錯誤:

Excel無法打開文件{Name} .xlsx,因為文件格式或文件擴展名無效。 驗證文件是否已損壞,以及文件擴展名是否與文件格式匹配

List<ExcelPackage> documents = new List<ExcelPackage>();
List<string> fileNames = new List<string>();

//Code for fetching documents and filenames here (removed for the sake of readability)

Response.Clear();
Context.Response.BufferOutput = false; 
Response.ContentType = "application/zip";
Response.AppendHeader("content-disposition", "attachment; filename=\"random-foldername.zip\"");
Response.CacheControl = "Private";
Response.Cache.SetExpires(DateTime.Now.AddMinutes(3)); 

ZipOutputStream zipOutputStream = new ZipOutputStream(Response.OutputStream);
zipOutputStream.SetLevel(3); //0-9, 9 being the highest level of compression
byte[] buffer = null;

for (int i = 0; i < documents.Count; i++)
{
    MemoryStream ms = new MemoryStream();

    documents[i].SaveAs(ms);

    ZipEntry entry = new ZipEntry(ZipEntry.CleanName(fileNames[i]));

    zipOutputStream.PutNextEntry(entry);
    buffer = new byte[ms.Length];

    ms.Read(buffer, 0, buffer.Length);
    entry.Size = ms.Length;

    ms.Close();

    zipOutputStream.Write(buffer, 0, buffer.Length);
    zipOutputStream.CloseEntry();

}
zipOutputStream.Finish();
zipOutputStream.Close();

Response.End();

至於文件名列表,我只是根據一些任意的東西生成一個名稱,並在其末尾添加一個“.xlsx” - 擴展。

我不知道我在哪里出錯了,有什么建議嗎?

您必須先回滾內存流,然后才能讀取內容(在寫入操作文件指針之后):

ms.Seek(0, SeekOrigin.Begin)
ms.Read(buffer, 0, buffer.Length);

這就是說MemoryStream只不過是一個字節數組,所以你甚至不需要分配和讀取一個新的代碼:

buffer = new byte[ms.Length];

ms.Read(buffer, 0, buffer.Length);
entry.Size = ms.Length;

ms.Close();

zipOutputStream.Write(buffer, 0, buffer.Length);

可以簡單地替換為:

entry.Size = ms.Length;
zipOutputStream.Write(ms.GetBuffer(), 0, ms.Length);
ms.Close();

最后注意:如果您不想使用內部MemoryStream緩沖區(出於任何原因)並且您想要它的修剪副本(當您手動執行時),那么只需使用ToArray()方法,如下所示:

var buffer = ms.ToArray();
ms.Close();
entry.Size = buffer.Length;
zipOutputStream.Write(buffer, 0, buffer.Length);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM