开发者

Corrupted file while compressing stream using dotnetzip library

开发者 https://www.devze.com 2023-04-11 04:41 出处:网络
The file is created and the size seems to be ok, but when I double click it is says its format is wrong or the file is damaged.

The file is created and the size seems to be ok, but when I double click it is says its format is wrong or the file is damaged.

This is the code I'm using

public MemoryStream Compres开发者_如何学运维sFiles(Dictionary<string, MemoryStream> filesToBeCompressed)
{
    var output = new MemoryStream();
    using (var zip = new ZipFile())
    {
        foreach (var entry in filesToBeCompressed)
        {
            entry.Value.Seek(0, SeekOrigin.Begin); // <-- must do this after writing the stream (I've read this in a blog
            zip.AddEntry(entry.Key.Substring(entry.Key.LastIndexOf('/') + 1, entry.Key.Length - entry.Key.LastIndexOf('/') - 1), entry.Value);
            zip.Save(output);
        }
    }
    return output;
}

Then in the calling method

SaveStreamToFile(documentCompressedName,getDocument());

getDocument() calls Compress internally

And that method finally

private static void SaveStreamToFile(string fileFullPath, Stream stream)
{
    if (stream.Length == 0) return;

    // Create a FileStream object to write a stream to a file
    using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
    {
        // Fill the bytes[] array with the stream data
        var bytesInStream = new byte[stream.Length];
        stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

        // Use FileStream object to write to the specified file
        fileStream.Write(bytesInStream, 0, bytesInStream.Length);
    }
}

Any ideas? Thanks in advance! Guillermo.


I think the problem is in your function SaveStreamToFile. You have to set the position of the stream to the beginning before you write the archive to disk:

private static void SaveStreamToFile(string fileFullPath, Stream stream)
{
  if (stream.Length == 0) return;

  // Set the position within the stream to the beginning of the stream
  stream.Seek(0, SeekOrigin.Begin);      

  // Create a FileStream object to write a stream to a file
  using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
  {
    // Fill the bytes[] array with the stream data
    var bytesInStream = new byte[stream.Length];
    stream.Read(bytesInStream, 0, (int)bytesInStream.Length);

    // Use FileStream object to write to the specified file
    fileStream.Write(bytesInStream, 0, bytesInStream.Length);
  }
}

Hope, this helps.


From your code snippets, my guess here is that the MemoryStream's Position is at the end of the stream when you pass it to SaveStreamToFile, and as you never set the position back to the start of the stream, your stream.Read is actually reading no bytes at all. If you open your output zip file with a hex editor, you'll probably see that it's full of zeros.

You have a number of options here, but my suggestion would be to try:

private static void SaveStreamToFile(string fileFullPath, Stream stream)
{
    if (stream.Length == 0) return;

    // Create a FileStream object to write a stream to a file
    using (FileStream fileStream = System.IO.File.Create(fileFullPath, (int)stream.Length))
    {
        // Use FileStream object to write to the specified file
        fileStream.Write(stream.GetBuffer(), 0, stream.Length);
    }
}

This approach avoids taking a copy of the internal memory buffer of the MemoryStream. Whilst I don't know how large your zip files are so it may not be an issue in terms of memory use, but storing the zip file in memory twice - once in the MemoryStream, and again in your original bytesInStream array seems unnecessary.

0

精彩评论

暂无评论...
验证码 换一张
取 消