SharpZipLib — добавление ZipEntry в ZipFile вызывает ZipException

Я пытаюсь создать ZIP с файлом из строки в памяти и сохранить его. Вот мой код:

var zip = ZipFile.Create(Path.Combine(outputPath, fileName));
zip.BeginUpdate();

var fileStream = new MemoryStream(Encoding.Default.GetBytes(myStringVariable));
var outputMemStream = new MemoryStream();
var zipStream = new ZipOutputStream(outputMemStream);
var zipEntry = new ZipEntry("file.html");

zipEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(zipEntry);
StreamUtils.Copy(fileStream, zipStream, new byte[4096]);
zipStream.CloseEntry();
zip.Add(zipEntry);

zip.CommitUpdate();
zip.Close();

Однако он ломается на zip.Add(zipEntry); и выдает исключение:

ZipException — запись не может содержать никаких данных

Что-то я не могу понять, что не так.


person Andrzej    schedule 20.02.2015    source источник


Ответы (1)


Переопределение метода ZipFile.Add, которое вы используете, предназначено для добавления каталогов, меток томов и т. д. в zip-файл: это явно выдает ZipException, если вы передаете ZipEntry, содержащий данные.

Согласно документации, если вы хотите добавить данные в памяти в ZipFile, вам нужно использовать переопределение Add(IStaticDataSource dataSource, string entryName). Вам также потребуется создать реализацию IStaticDataSource (приведенная ниже версия взята со страницы документации).

Таким образом, ваш код будет выглядеть примерно так:

void Main()
{
    string outputPath = @"C:\Scratch\test.zip";
    string myStringVariable = "<html><head><title>Title</title></head><body>Hello World</body></html>";

    var zip = ZipFile.Create(outputPath);
    zip.BeginUpdate();

    var fileStream = new MemoryStream(Encoding.Default.GetBytes(myStringVariable));

    var dataSource = new CustomStaticDataSource();
    dataSource.SetStream(fileStream);

    zip.Add(dataSource, "file.html");

    zip.CommitUpdate();
    zip.Close();
}

public class CustomStaticDataSource : IStaticDataSource {
    private Stream _stream;
    // Implement method from IStaticDataSource
    public Stream GetSource() {
        return _stream;
    }

    // Call this to provide the memorystream
    public void SetStream(Stream inputStream) {
        _stream = inputStream;
        _stream.Position = 0;
    }
}
person pixelbadger    schedule 20.02.2015
comment
Отлично, работает. Однако я должен признать, что это не интуитивное решение. - person Andrzej; 20.02.2015