Ziparchive解包多部分zip文件

本文关键字:zip 文件 包多部 Ziparchive | 更新日期: 2023-09-27 18:18:02

我希望通过ZipArchive解压缩多部分zip文件。解压缩一个"独立"的zip文件工作,但如果我试图解压缩第一个文件,它只是抛出一个错误。它在windows资源管理器中是这样工作的(只是解压缩第一个文件),所以我猜它可能有效,因为我在网上找不到任何其他方法。

using (ZipArchive archive = new ZipArchive(fs)) {
    archive.ExtractToDirectory(tempLocation, true);
}

但是,也许这是一个XY问题,所以我使用它作为块文件下载的简化方式。我们将这个用于updateservice,它下载更新的内容。为了灵活一点,我们将使用(多部分)zip文件。如果这是错误的方法,请告诉我。

编辑:在弄清楚第一个错误是PEBCAK后,我得到了"不支持分裂或传播档案"的错误。

是否有其他Zipfile库支持它?

Ziparchive解包多部分zip文件

我建议使用DotNetZip来完成您想要的。

首先,您必须将所有的".zip "文件组合在一起。001 . zip。002 . zip。将003"的文件合并成一个大文件,然后按照正常方式解压:

        string destFileName = @"C:'Temp'zip'finalHugeFile.zip";
        List<string> myMultiPartZip00xFiles = System.IO.Directory.GetFiles(@"C:'Temp'zip", "*.zip.*").ToList();
        using (Stream destStream = File.OpenWrite(destFileName))
        {
            foreach (string srcFileName in myMultiPartZip00xFiles)
            {
                using (Stream srcStream = File.OpenRead(srcFileName))
                {
                    srcStream.CopyTo(destStream);
                }
            }
        }
        // we extract here
        using (ZipFile zip = ZipFile.Read(destFileName))
        {
            foreach (ZipEntry entry in zip)
            {
                entry.Extract(@"C:'Temp'zip", ExtractExistingFileAction.OverwriteSilently);
            }
        }

Multipart zip只是一个普通的zip文件。因此,我们需要一个Stream,将多个文件合并为一个:

var multiFileStream = new MultiFileStream(new[] { "a.001", "a.002" });
using var zip = new ZipArchive(multiFileStream);
// ...
public class MultiFileStream : Stream
{
    private readonly IList<string> _files;
    private int _fileIdx;
    private FileStream? _file;
    public MultiFileStream(IList<string> files)
    {
        _files = files;
    }
    public override int Read(byte[] buffer, int offset, int count)
    {
        while (true)
        {
            _file ??= File.OpenRead(_files[_fileIdx]);
            var res = _file.Read(buffer, offset, count);
            if (res > 0)
            {
                return res;
            }
            _file.Dispose();
            _file = null;
            if (_fileIdx < _files.Count - 1)
            {
                _fileIdx++;
            }
            else
            {
                return 0;
            }
        }
    }
    public override void Flush() => throw new NotSupportedException();
    public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
    public override void SetLength(long value) => throw new NotSupportedException();
    public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
    public override bool CanRead => true;
    public override bool CanSeek => false;
    public override bool CanWrite => false;
    public override long Length => throw new NotSupportedException();
    public override long Position
    {
        get => throw new NotSupportedException();
        set => throw new NotSupportedException();
    }
}

另一个答案是有效的,但由于临时文件和所有的复制(大档案甚至可能耗尽磁盘空间),速度要慢得多。