Delphi TZipFile提取零字节文件

时间:2017-04-12 14:27:06

标签: delphi zip delphi-xe2 zipfile

使用Delphi XE2和本机TZipFile我尝试提取下载的zip文件(包含2个压缩的XML文件)的内容,并始终提取零字节文件。

该文件正在被C#代码压缩,如下所示:

toUInt32()

Delphi提取代码是这样的:

var zipFile = new ZipFile();
foreach (Tuple<string, string> t in filesMeta) {
  zipFile.AddFile(string.Format("{0}{1}", StaticVariables.WebServerFileStorage, t.Item2), "").FileName = t.Item1 + ".xml";
}
response.Clear();
response.ContentType = "application/zip";
zipFile.Save(response.OutputStream);
response.End();

我甚至尝试使用TStream作为源而不是磁盘上的文件。这实际上是我想要做的事情,因为zip文件是从Web服务器下载到TStream中的。我尝试使用TZipFile的重载open方法提取数据来打开流。

这让我得到零字节文件,所以我将zip文件保存到磁盘并尝试从磁盘打开文件并解压缩。提取相同的零字节文件。

我甚至尝试使用class方法从磁盘上的zip文件中提取文件:

zipFile := TZipFile.Create;
try
  filename := 'C:\test\57f52480-ec87-4169-a820-0a65bc4ad952.zip';
  if zipFile.IsValid(filename) then begin
    zipFile.Open(filename, zmRead);
    zipFile.ExtractAll('C:\test\');
  end;
finally
  zipFile.Free;
end;

提取相同的零字节文件。

zip文件有效,可以通过Windows 7本机文件处理和7-Zip正确提取2个压缩的XML文件。

现在这里有点坚果......

在绝望中我试图看看ExtractToFile()程序是什么  David Heffernan在这个问题中想出了extracting a zip to a stream会这样做我尝试使用它是这样的:

System.Zip.TZipFile.ExtractZipFile(filename, 'C:\Test\');

David的程序按预期将文件提取到磁盘! WTF ???

我真的很困惑为什么一个错综复杂的提取方法会起作用,而简单的提取方法也行不通。如果必须,我会使用David的例子,但如果可能的话,我更愿意让正常的提取物工作。

任何想法都表示赞赏。

干杯! TJ

2 个答案:

答案 0 :(得分:0)

TL; DR:我的问题的解决方案是外部组件。 Zip Forge(或Abbrevia)

继续阅读详情。

除了拯救文件的迂回方式并使用David的功能重新打开它之外,我没有尝试过。虽然这样可行,但它并不是最佳的,因为它要求我先将下载的文件保存到磁盘并重新打开以进行提取,然后删除zip文件。我的目标是打开下载的流并将文件直接解压缩到磁盘。一次写入磁盘而没有临时文件。

我们甚至尝试了两个不同的C#库来压缩文件,两者都在流数据上给出了相同的结果。 Delphi TZipFile组件无法处理它。

事实证明,我们已经忘记了ZipForge的许可,因为我已经很久没有使用它了,它处理来自C#Web服务器的下载流并成功提取文件。

作为参考,我还尝试了Abbrevia组件版本5.2,并且还成功地从流中提取了文件。

希望这会帮助别人。

David和Uwe的所有建议都表示赞赏。

干杯!

TJ

答案 1 :(得分:0)

我遇到了同样的问题。

TZipFile 的源代码显示,传递给 Read 函数的 TStream 返回整个 zip 文件,位置设置为您想要的文件名的开头。所以不要倒带。对于 TZipHeader 中给定的未压缩长度,只需复制或使用 TStream 执行您想要的操作。

ZipStream := TStream.Create;
ZipFile.Read(MyFileName, ZipStream, ZipHeader);
//leave ZipStream pointer where it is!!!
SomethingElse.LoadFromStream(ZipStream, ZipHeader.UncompressedSize);
ZipStream.Free;

在我看来,TZipFile 应该真正加载 ZipStream,其中只包含请求的内容。如果不首先查看 TZipFile 源代码,这种实现方式并不直观。