基于内存流大小将Excel文件压缩为Zip文件的实现疑问
解决Excel内存流压缩为Zip文件的问题
原代码存在的问题
- 写完Excel后,
stream的位置停留在末尾,未重置到起始位置,导致后续读取流内容为空 - 创建Zip条目后,未将Excel的流内容写入到Zip条目流中
- 变量名错误:使用了未定义的
memoryStream,实际应为stream - ZipArchive的创建逻辑有误,直接使用原Excel流创建Zip会覆盖原有内容,需要单独的流来存储Zip数据
修正后的完整代码
var excelStream = new MemoryStream(); string fileName = "Sheet1.xlsx"; // 定义Zip内的Excel文件名 // 1. 创建Excel文档并写入到内存流 using (SpreadsheetDocument document = SpreadsheetDocument.Create(excelStream, SpreadsheetDocumentType.Workbook)) { WorkbookPart workbookPart = document.AddWorkbookPart(); workbookPart.Workbook = new Workbook(); WorksheetPart worksheetPart = workbookPart.AddNewPart<WorksheetPart>(); var sheetData = new SheetData(); worksheetPart.Worksheet = new Worksheet(sheetData); Sheets sheets = workbookPart.Workbook.AppendChild(new Sheets()); var workSheet = new Sheet() { Id = workbookPart.GetIdOfPart(worksheetPart), SheetId = 1, Name = "Sheet1" }; sheets.Append(workSheet); worksheetPart.Worksheet.Save(); workbookPart.Workbook.Save(); document.Save(); // using块会自动处理Close,无需手动调用 } // 重置Excel流的位置到起始点,准备读取内容 excelStream.Seek(0, SeekOrigin.Begin); byte[] fileData = excelStream.ToArray(); var fileSize = fileData.Length; if (fileSize > 1000) { // 创建新内存流存储Zip文件内容 using (var zipStream = new MemoryStream()) { // 初始化Zip归档 using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { // 在Zip中创建Excel条目 var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Fastest); // 将Excel流内容写入Zip条目 using (var entryStream = fileInArchive.Open()) { excelStream.Seek(0, SeekOrigin.Begin); excelStream.CopyTo(entryStream); } } // 将Zip流写入本地文件 zipStream.Seek(0, SeekOrigin.Begin); using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create)) { zipStream.CopyTo(fileStream); } } } // 释放资源 excelStream.Close(); await excelStream.DisposeAsync();
关键修正点说明
- 流位置重置:每次读取流前必须用
Seek(0, SeekOrigin.Begin)将指针移到起始位置,否则读取不到有效内容 - 分离流职责:用独立的
zipStream存储Zip内容,避免和原Excel流的读写操作冲突 - 写入Zip条目:通过
CopyTo方法将Excel流的内容完整写入到Zip条目的流中,完成压缩逻辑 - using块优化:利用using块自动管理资源生命周期,避免手动调用Close可能引发的错误
内容的提问来源于stack exchange,提问作者TheProgrammer
相关产品推荐
相关产品推荐

