Delphi TZipFile提取零字节文件

Delphi TZipFile提取零字节文件,delphi,zip,delphi-xe2,zipfile,Delphi,Zip,Delphi Xe2,Zipfile,使用Delphi XE2和本机TZIP文件,我尝试提取下载的zip文件(其中包含2个压缩的XML文件)的内容,它总是提取零字节文件 文件正在被C代码压缩,如下所示: var zipFile = new ZipFile(); foreach (Tuple<string, string> t in filesMeta) { zipFile.AddFile(string.Format("{0}{1}", StaticVariables.WebServerFileStorage, t.I

使用Delphi XE2和本机TZIP文件,我尝试提取下载的zip文件(其中包含2个压缩的XML文件)的内容,它总是提取零字节文件

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

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();
var x : integer;
var fileCount : integer;
var fileNames : TArray<string>;
begin
  zipFile := TZipFile.Create;
  try
    filename := 'C:\test\57f52480-ec87-4169-a820-0a65bc4ad952.zip';
    if zipFile.IsValid(filename) then begin
      zipFile.Open(filename, zmRead);
      fileCount := zipFile.FileCount;
      fileNames := copy(zipFile.FileNames, 0, MaxInt);
      zipFile.Close;

      for x := 0 to fileCount-1 do begin
        // Use David Heffernan's stream procedure
        ExtractToFile(filename, x, 'C:\test\' + fileNames[x]);
      end;
    end;
  finally
    zipFile.Free;
  end;
end;
我甚至尝试使用TStream作为源,而不是磁盘上的文件。这正是我想要做的,因为zip文件是从web服务器下载到TStream中的。我尝试使用TZipFile的重载打开方法来提取数据,以打开流

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

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

System.Zip.TZipFile.ExtractZipFile(filename, 'C:\Test\');
提取相同的零字节文件

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

现在这里有一些疯狂的东西。。。 在绝望中,我试图查看ExtractToFile()过程是什么 David Heffernan在这个问题中提出了关于“我会做什么”,所以我试着这样使用它:

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();
var x : integer;
var fileCount : integer;
var fileNames : TArray<string>;
begin
  zipFile := TZipFile.Create;
  try
    filename := 'C:\test\57f52480-ec87-4169-a820-0a65bc4ad952.zip';
    if zipFile.IsValid(filename) then begin
      zipFile.Open(filename, zmRead);
      fileCount := zipFile.FileCount;
      fileNames := copy(zipFile.FileNames, 0, MaxInt);
      zipFile.Close;

      for x := 0 to fileCount-1 do begin
        // Use David Heffernan's stream procedure
        ExtractToFile(filename, x, 'C:\test\' + fileNames[x]);
      end;
    end;
  finally
    zipFile.Free;
  end;
end;
var x:integer;
var fileCount:整数;
var文件名:TArray;
开始
zipFile:=TZipFile.Create;
尝试
文件名:=“C:\test\57f52480-ec87-4169-a820-0a65bc4ad952.zip”;
如果zipFile.IsValid(文件名)则开始
打开(文件名,zmRead);
fileCount:=zipFile.fileCount;
文件名:=副本(zipFile.fileNames,0,MaxInt);
zipFile.关闭;
对于x:=0到fileCount-1,请开始
//使用David Heffernan的流程序
ExtractToFile(文件名,x,'C:\test\'+文件名[x]);
结束;
结束;
最后
免费;
结束;
结束;
David的过程按预期将文件提取到磁盘!WTF

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

欢迎提出任何意见

干杯!
TJTL;DR:我的问题的解决方案是一个外部组件。Zip Forge(或Abbrevia)

请继续阅读以了解详细信息

除了保存文件并使用David的函数重新打开它的迂回方式外,我什么也没试过。虽然这样做是可行的,但它并不是最优的,因为它需要我先将下载的文件保存到磁盘,然后重新打开进行解压缩,然后删除zip文件。我的目标是打开下载的流并将文件直接解压缩到磁盘。一次磁盘写入,没有临时文件

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

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

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

希望这能帮助其他人

David和Uwe的所有建议都得到了赞赏

干杯


TJ

我无法重现这一点。除非我们能复制它,否则这将很难。我们可能也需要你的ZIP文件。您是如何创建的?@David-该文件是在web服务器上使用问题中显示的C代码创建的。文件从存储区域中取出并压缩。不是我的代码,但我是从写代码的人那里得到的。如果我需要提供示例zip文件,我可以这样做。我认为这是必要的。通过尝试提取在explorer中生成的简单zip文件,让自己相信这一点。然后找出它们的不同之处。@David-好吧,你可能知道了一些事情。我用Windows资源管理器压缩了驱动器上的两个XML文件,该文件提取得很好。我查看了zipFile.Read()方法的头,对于失败的文件,CompressedSize和UncompressedSize都为零。我似乎记得看到过一篇关于这个的帖子,但现在找不到。在Explorer或7-Zip中压缩的所有文件的大小都不为零。能否检查标志字段的第3位是否设置在本地标题中?这对TZipFile不起作用。