IO :: Compress :: Zip从文件句柄读入缓冲区

时间:2013-04-23 11:33:16

标签: perl io compression zip cpan

我正在尝试动态构建压缩的xml文件并将其发送到浏览器。我正在使用IO::Compress::ZipIO::String,但它不能像文档中那样有效。

首先是我的代码:

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}是一个具有以下结构的arrayref:

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

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

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

当我尝试将文件下载为带有一个空文件的.zip-archive时,我得到了所有内容。我在这里做错了什么提示?

提前致谢。

编辑:这很奇怪。我现在试过这个:

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;

档案仍然是空的。

2 个答案:

答案 0 :(得分:1)

zip的 附加 选项没有达到预期效果。它不会更新现有的zip文件。它创造了一个新的&amp;将它附加到您提供的文件/缓冲区。在您的情况下,您将最终得到一系列拉链容器背靠背。

这是使用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;

答案 1 :(得分: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;