You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ZipArchive生成压缩包可见文件但解压后文件夹为空问题咨询

问题:生成的Zip包在Windows中可见文件但解压后为空

以下是用于生成并下载包含foo.txt文件的压缩包的代码:

public async Task<IActionResult> DownloadZip()
{
    using (var zipStream = new MemoryStream())
    {
        using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
        {
            var zipEntry = zipArchive.CreateEntry("foo.txt");

            using var entryStream = zipEntry.Open();

            using (var streamWriter = new StreamWriter(entryStream))
            {
                streamWriter.Write("bar");
            }
        }

        zipStream.Position = 0;

        return File(zipStream.ToArray(), "application/zip", "file.zip");
    }
}

原因分析

出现这个问题的核心原因是流被重复关闭导致归档元数据不完整:

  • StreamWriter的默认构造行为会在Dispose时关闭其基础流(即entryStream)
  • 你使用了C# 8的using var声明entryStream,它会在所在代码块(ZipArchive的using块)结束时再次尝试释放entryStream
  • 重复关闭流会导致ZipArchive无法正确写入完整的归档元数据(比如中央目录记录)
  • Windows资源管理器预览Zip时仅读取局部文件头,所以能看到foo.txt条目;但解压工具依赖完整的元数据,因此无法提取文件,导致解压后文件夹为空

解决方法

方法一:指定StreamWriter不关闭基础流

修改StreamWriter的构造方式,添加leaveOpen: true参数,避免它关闭entryStream,让using var声明负责流的释放:

public async Task<IActionResult> DownloadZip()
{
    using (var zipStream = new MemoryStream())
    {
        using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
        {
            var zipEntry = zipArchive.CreateEntry("foo.txt");

            using var entryStream = zipEntry.Open();
            // 指定leaveOpen: true,让StreamWriter不关闭基础流
            using (var streamWriter = new StreamWriter(entryStream, leaveOpen: true))
            {
                streamWriter.Write("bar");
            }
        }

        zipStream.Position = 0;
        return File(zipStream.ToArray(), "application/zip", "file.zip");
    }
}

方法二:使用嵌套using块保证释放顺序

改用传统嵌套using块的方式,确保流的释放顺序正确,避免重复关闭:

public async Task<IActionResult> DownloadZip()
{
    using (var zipStream = new MemoryStream())
    {
        using (var zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
        {
            var zipEntry = zipArchive.CreateEntry("foo.txt");
            using (var entryStream = zipEntry.Open())
            using (var streamWriter = new StreamWriter(entryStream))
            {
                streamWriter.Write("bar");
            }
        }

        zipStream.Position = 0;
        return File(zipStream.ToArray(), "application/zip", "file.zip");
    }
}

两种方式都能避免流的重复关闭,确保ZipArchive写入完整的归档数据,解压后就能正常看到foo.txt文件了。

内容的提问来源于stack exchange,提问作者DarkLeafyGreen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:52:18