Поврежденный файл при сжатии потока с использованием библиотеки dotnetzip - PullRequest
1 голос
/ 05 октября 2011

Файл создан, и его размер кажется приемлемым, но когда я дважды щелкаю по нему, он говорит, что его формат неправильный или файл поврежден.

Это код, который я использую

public MemoryStream CompressFiles(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;
}

Тогда в методе вызова

SaveStreamToFile(documentCompressedName,getDocument());

getDocument () вызывает внутреннее сжатие

И этот метод, наконец,

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);
    }
}

Есть идеи? Заранее спасибо! Гильермо.

Ответы [ 2 ]

3 голосов
/ 05 октября 2011

Я думаю, что проблема в вашей функции SaveStreamToFile.Перед записью архива на диск необходимо установить позицию потока в начало:

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);
  }
}

Надеюсь, это поможет.

1 голос
/ 05 октября 2011

Исходя из ваших фрагментов кода, я предполагаю, что MemoryStream в Position находится в конце потока, когда вы передаете его в SaveStreamToFile, и, поскольку вы никогда не устанавливаете позицию обратно в начало потока, вашstream.Read фактически не читает байтов вообще.Если вы откроете выходной zip-файл в шестнадцатеричном редакторе, вы, вероятно, увидите, что он полон нулей.

У вас есть несколько вариантов здесь, но я бы предложил попробовать:

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);
    }
}

Этот подход позволяет избежать копирования внутренней буфера памяти MemoryStream.Хотя я не знаю, насколько велики ваши zip-файлы, так что это может быть проблемой с точки зрения использования памяти, но сохранение zip-файла в памяти дважды - один раз в MemoryStream и снова в исходном массиве bytesInStreamкажется ненужным.

...