ASP.NET Core Web Api使用ZipArchive生成压缩包无法打开问题排查
解决ASP.NET Core 2 Web API中动态生成可打开压缩文件夹的问题
我一眼就发现了代码里的核心问题——你在ZipArchive的using块内部就调用了zipStream.ToArray(),这时候压缩归档还没完成最终的写入操作!
问题原因
当使用ZipArchiveMode.Create创建压缩包时,ZipArchive会在它被**释放(Dispose)**的时候才完成所有收尾工作:包括写入压缩包的目录结构、校验信息和结尾标记。如果在ZipArchive还没释放就读取底层的MemoryStream,得到的字节数组是不完整的,这就导致下载后的zip文件看起来大小正常,但实际上是损坏的,无法打开。
修正后的代码
把bytes = zipStream.ToArray()移到ZipArchive的using块外面,确保压缩归档完成所有写入后再提取数据:
[HttpGet] [Route("/api/download/zip")] public async Task<IActionResult> Zip() { byte[] bytes = null; using (MemoryStream zipStream = new MemoryStream()) { using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true)) { var tempFileName = await _azure.GetFilesByRef("Azure_FilePath"); ZipArchiveEntry entry = zip.CreateEntry("File1.pdf", CompressionLevel.Fastest); using (Stream stream = entry.Open()) using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read)) { await fs.CopyToAsync(stream); } } // 等ZipArchive释放后,再读取完整的压缩数据 bytes = zipStream.ToArray(); } return File(bytes, MediaTypeNames.Application.Zip, $"Attachments{DateTime.Now.ToBinary()}.zip"); }
额外检查项
- 确认
tempFileName指向的文件确实存在,并且你的应用程序有读取该文件的权限 - 如果需要添加多个文件,重复
CreateEntry和文件复制的逻辑即可 - 文件名中的
DateTime.Now.ToBinary()可能会生成不太友好的文件名,建议换成更易读的格式,比如DateTime.Now.ToString("yyyyMMddHHmmss")
内容的提问来源于stack exchange,提问作者shammelburg
相关产品推荐
相关产品推荐

