如何从文件字节开始在内存中创建zip文件?

5

我尝试使用C#在内存中创建一个zip文件,但结果是一个包含损坏文件的zip文件。所有需要压缩的文件都存储在数据库中,我将它们的字节存储起来。这些文件是PDF格式的。以下是我的代码:

//[extract bytes and file name for every file]

using (var zipArchiveMemoryStream = new MemoryStream())
{
    using (var zipArchive = new ZipArchive(zipArchiveMemoryStream,
                                           ZipArchiveMode.Create, true))
    {
        foreach (var file in fileData)
        {
            var zipEntry = zipArchive.CreateEntry(file.FileName);
            using (var entryStream = zipEntry.Open())
            {
                using (var tmpMemory = new MemoryStream(file.Bytes))
                {
                    tmpMemory.CopyTo(entryStream);
                };

            }
        }
    }
    zipArchiveMemoryStream.Position = 0;
    result = zipArchiveMemoryStream.GetBuffer();

//[download zip file]

感谢您的支持。

TONIGNO提供的解决方案: 问题是我使用了GetBuffer()而不是ToArray()。

using (var zipArchiveMemoryStream = new MemoryStream())
        {
            using (var zipArchive = new ZipArchive(zipArchiveMemoryStream, ZipArchiveMode.Create, true))
            {
                foreach (var file in fileData)
                {
                    var zipEntry = zipArchive.CreateEntry(file.FileName);
                    using (var entryStream = zipEntry.Open())
                    {
                        using (var tmpMemory = new MemoryStream(file.Bytes))
                        {
                            tmpMemory.CopyTo(entryStream);
                        };

                    }
                }
            }

            zipArchiveMemoryStream.Seek(0, SeekOrigin.Begin);
            result = zipArchiveMemoryStream.ToArray();
        }

        return result;


你的代码有什么问题? - Yuval Itzchakov
我无法从压缩文件中提取文件。WinRAR显示文件已损坏。 - Luca Dalsass
2个回答

5

请参考以下内容:使用System.IO.Compression在内存中创建ZIP归档文件。解决方案如下:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var demoFile = archive.CreateEntry("foo.txt");

      using (var entryStream = demoFile.Open())
      using (var streamWriter = new StreamWriter(entryStream))
      {
         streamWriter.Write("Bar!");
      }
   }

   using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
   {
      memoryStream.Seek(0, SeekOrigin.Begin);
      memoryStream.CopyTo(fileStream);
   }
}

本文介绍如何在内存中创建zip归档文件,并包含一个链接到另一篇有用的文章,该文章说明了使用leaveOpen参数以防止流关闭的方法:ZipArchive creates invalid ZIP file,其中包含了此解决方案:

using (MemoryStream zipStream = new MemoryStream())
{
    using (ZipArchive zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        var entry = zip.CreateEntry("test.txt");
        using (StreamWriter sw = new StreamWriter(entry.Open()))
        {
            sw.WriteLine(
            "Etiam eros nunc, hendrerit nec malesuada vitae, pretium at ligula.");
        }
    }

    var file = await Windows.Storage.ApplicationData.Current.LocalFolder.CreateFileAsync(
    "test.zip",
    CreationCollisionOption.ReplaceExisting);

    zipStream.Position = 0;
    using (Stream s = await file.OpenStreamForWriteAsync())
    {
        zipStream.CopyTo(s);
    }
}

希望有所帮助!

编辑

请使用zipArchiveMemoryStream.ToArray()代替zipArchiveMemoryStream.GetBuffer()


虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Gerald Versluis
1
好的,对不起!谢谢你的建议! - Tonigno
没问题,把它当作一条建议吧!;) - Gerald Versluis
我再试一次,但我已经阅读了链接的文章。我的情况不同之处在于,我没有物理文件,只有字节。在压缩之前我不能将它保存在硬盘上。我会告诉你。 - Luca Dalsass
好的,不要使用zipArchiveMemoryStream.GetBuffer(),尝试使用zipArchiveMemoryStream.ToArray() - Tonigno

0

对我来说,它是这样工作的:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var file = archive.CreateEntry("file.json");
      using var entryStream = file.Open();
      using var streamWriter = new StreamWriter(entryStream);
      streamWriter.WriteLine(someJsonLine);
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接