将zip文件保存到内存并从流中解压缩文件并获取内容

时间:2017-03-17 14:51:35

标签: c# zip

我目前正致力于在我们的系统上集成Amazon Prime,并坚持以ZPL格式取回标签。

基本上,Amazon返回base64字符串,我们需要将该字符串转换为字节数组,然后将该数组保存为* .gzip文件。从该gzip文件中,我们可以提取内容并获取zpl标签内容。

我的问题是,如何在不将任何临时文件存储到系统的情况下完成上述所有操作。我研究了一些解决方案,但没有一个对我有用。

我目前的代码如下:

var str = "base64string";    
var label = Convert.FromBase64String(str);

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

        var entryStream = demoFile.Open();

        using (var bw = new BinaryWriter(entryStream))
        {
            bw.Write(label);
        }

        var data = new MemoryStream();

        using (var zip = ZipFile.Read(entryStream))
        {
            zip["label"].Extract(data);
        }

        data.Seek(0, SeekOrigin.Begin);

        entryStream.Close();
    }

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

如果我将文件保存为test.zip,我可以成功获取标签。但是,如果我尝试将其直接提取到另一个流,我会收到错误

  

来自ZipArchiveEntry的流已被处理

2 个答案:

答案 0 :(得分:1)

我做过类似的事情,从压缩的网页回复中获取PNG标签数据。这就是我的方式

using (WebClient webClient = new WebClient()) 
{
    // Download. Expect this to be a zip file
    byte[] data = webClient.DownloadData(urlString);

    MemoryStream memoryStream = new MemoryStream(data);

    ZipArchive zipArchive = new ZipArchive(memoryStream);

    foreach (var zipEntry in zipArchive.Entries)
    {
        // Can check file name here and ignore anything in zip we're not expecting
        if (!zipEntry.Name.EndsWith(".png")) continue;

        // Open zip entry as stream
        Stream extractedFile = zipEntry.Open();

        // Convert stream to memory stream
        MemoryStream extractedMemoryStream = new MemoryStream();
        extractedFile.CopyTo(extractedMemoryStream);

        // At this point the extractedMemoryStream is a sequence of bytes containing image data. 
        // In this test project I'm pushing that into a bitmap image, just to see something on screen, but could as easily be written to a file or passed for storage to sql or whatever.
        BitmapDecoder decoder = PngBitmapDecoder.Create(extractedMemoryStream, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);
        BitmapFrame frame = decoder.Frames.First();
        frame.Freeze();
        this.LabelImage.Source = frame;
    }
}

答案 1 :(得分:0)

我在思考它。我终于找到了一种简单的方法。我们只需要将base64字符串转换为bytes数组,并使用GzipStream直接解压缩它。我将解决方案留在这里以防有人需要它。谢谢!

var label = Convert.FromBase64String(str);

        using (var compressedStream = new MemoryStream(label))
        using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
        using (var resultStream = new MemoryStream())
        {
            zipStream.CopyTo(resultStream);
            return resultStream.ToArray();
        }