2013-04-23 51 views
1

我试图快速构建一个压缩的xml文件并将其发送到浏览器。我正在使用IO::Compress::ZipIO::String,但它不起作用,正如我期望的那样。IO :: Compress :: Zip从文件句柄读入缓冲区

首先我的代码:

my $zipped_file; 
foreach (@{$par{directory}}) { 
    my $input = IO::String->new($_->[0]); 
    zip $input => \$zipped_file, Append => 1, BinModeIn => 1|0; # Tried both for BinModeIn 
} 
return $zipped_file; 

$par{directory}是具有以下结构的数组引用:

[ 
    ['DATA', 'FILENAME'], ['DATA', 'FILENAME'], ... 
] 

$par{directory}的数据是这样的字符串:

<?xml version="1.0" encoding="UTF-8"?> 
<derivatives> 
    <derivative ag="111520420" vhash="d6712f201155a9afb64dc5a5ba369c99"> 
     //Some data 
    </derivative> 
</derivatives> 

所有我得到,当我尝试下载该文件作为与一个emp的.zip档案ty文件。我在这里做错了什么暗示?

在此先感谢。

编辑:这是奇怪的。我现在试过了:

use strict; 
use warnings; 
use IO::Compress::Zip 'zip'; 

my $xml1 = <<END_XML; 
    <?xml version="1.0" encoding="UTF-8"?> 
    <derivatives> 
     <derivative ag="111520420" vhash="d6712f201155a9afb64dc5a5ba369c99"> 
      //Some data 
     </derivative> 
    </derivatives> 
END_XML 

my $xml2 = <<END_XML; 
    <?xml version="1.0" encoding="UTF-8"?> 
    <derivatives2> 
     <derivative2 ag="111520420" vhash="d6712f201155a9afb64dc5a5ba369c99"> 
      //Some data 
     </derivative2> 
    </derivatives2> 
END_XML 

my $files = [[$xml1, 'xml1'], [$xml2, 'xml2']]; 
my $zipped_file; 

foreach (@$files) { 
    open my $input, '<', \$_->[0]; 
    zip $input => \$zipped_file, Append => 1, BinModeIn => 1; 
} 

open my $fh, '>:raw', 'zip.zip'; 
print $fh $zipped_file; 
close $fh; 

存档仍为空。

+0

尝试改变拉链线到此'拉链$输入=> \ $ zipped_file,追加=> 1,名称=> $ _-> [1],BinModeIn => 1;' – pmqs 2013-04-23 15:28:28

回答

1

追加选项拉链不是做你的期望。它不更新现有的zip文件。它创建一个新的&将其附加到您提供的文件/缓冲区。在你的情况下,你将最终得到一系列紧接着的zip容器。

这里有一种方法来实现你想要的东西Archive :: Zip :: SimpleZip - 这只是一个包装IO :: Compress :: Zip的包装来处理这种类型的用例。

use Archive::Zip::SimpleZip ; 

my $zipped_file; 
my $zip = new Archive::Zip::SimpleZip \$zipped_file ; 
foreach (@{$par{directory}}) { 
    $zip->addString($_->[0], Name => $_->[1]); 
} 
$zip->close(); 
return $zipped_file; 
+0

工作原理:-D 对于'IO :: Compress :: Gzip',有没有类似于'Archive :: Zip :: SimpleZip'的东西?因为我必须同时使用gzip和zip。 – Vince 2013-04-23 14:22:46

+0

对不起,Archive :: Zip :: SimpleZip仅适用于Zip文件。 如果您只是用IO :: Compress :: Gzip替换IO :: Compress :: Zip,并使用“gzip”而不是“zip”,那么您的原始方法应该可以正常工作。有些东西是这样的(未经测试) gzip \ $ _-> [0] => \ $ zipped_file,Append => 1,Name => $ _-> [1]; gzip规范(RFC 1952)允许背靠背的gzip文件,所以在这种情况下,Append选项可以。 浏览器是否可以处理串联的gzip文件是另一回事。 – pmqs 2013-04-23 14:50:32

+0

那么,不应该我的方法工作,但Append => 0,只有一个文件? – Vince 2013-04-23 15:06:08

0

我认为这个问题更可能与您在创建$zipped_file后所做的工作有关。

下面的程序适合我。我已将压缩字符串写入二进制文件,并使用单独的实用程序解压缩它,以提供原始XML。

我宁愿放弃IO::String,而是使用内置的open my $input, '<', \$_->[0]来代替,但它似乎可以工作。

use strict; 
use warnings; 

use IO::Compress::Zip 'zip'; 
use IO::String; 

my $xml = <<END_XML; 
<?xml version="1.0" encoding="UTF-8"?> 
<derivatives> 
    <derivative ag="111520420" vhash="d6712f201155a9afb64dc5a5ba369c99"> 
     //Some data 
    </derivative> 
</derivatives> 
END_XML 

my $zipped_file; 

my $input = IO::String->new($xml); 

zip $input => \$zipped_file, Append => 0, BinModeIn => 1; 

open my $fh, '>:raw', 'zip.zip'; 
print $fh $zipped_file; 
close $fh; 

更新

顺便说一句,似乎没有必要在所有打开IO流输入数据:你可以传给包含数据的标量的参考。所以上面就像变成

my $zipped_file; 

zip \$xml => \$zipped_file, Append => 0, BinModeIn => 1; 

open my $fh, '>:raw', 'zip.zip'; 
print $fh $zipped_file; 
close $fh; 
+0

我已经试过它也是如此,但由于它不适合我,我试着用文件句柄来做。 – Vince 2013-04-23 13:09:29

+0

嗯。两者对我来说都是一样的。 – Borodin 2013-04-23 13:14:45

+0

我已经将您的代码复制到脚本中,但它仍然不适用于我。没有错误,没有什么,只是一个空的zip档案,我不能解压缩(mapname:转换失败)。 它可能与事实有关,我不能传递文件内的文件的名称? – Vince 2013-04-23 13:28:02