【问题标题】:String to Zipped Stream in php字符串到 php 中的压缩流
【发布时间】:2012-07-14 09:10:43
【问题描述】:

我有一个带有我的数据库的处理服务器和一个服务数据库,用于以低带宽成本提供文件。在处理服务器上,php 无法创建文件,因此在发送到另一台服务器进行下载之前,必须使用流完成所有操作和/或保留在内存中。几天前,我发现了 'php://memory' 的流抽象,我可以做类似的事情

$fp=fopen('php://memory','w+');
fwrite($fp,"Hello world");
fseek($fp,0,SEEK_SET);

//make a ftp connection here with $conn_id
$upload = ftp_fput($conn_id,"targetpath/helloworld.txt",$fp,FTP_BINARY);

在内存中创建文件,然后允许我将其通过 ftp 传输到我的其他服务器。这正是我想要的,除了我还想在发送数据之前压缩数据——最好只使用 php 的本机部分,如 ziparchive,而不是额外的自定义类来进行特殊的流操作。我知道我非常接近以下...

$zip = new ZipArchive();
if($zip->open('php://memory', ZIPARCHIVE::CREATE)) {
  $zip->addFromString('testtext.txt','Hello World!');
  $fp = $zip->getStream('test'); if(!$fp) print "no filepointer";

  //make a ftp connection here with $conn_id
  $upload = ftp_fput($conn_id,"targetpath/helloworld.zip",$fp,FTP_BINARY);
} else print "couldn't open a zip like that";

失败的地方是对 getStream 的调用(尽管我认为我使用正确,但它总是返回 false)。似乎 zip 可以很好地在 'php://memory' 中制作文件,但由于某种原因 getStream 仍然失败,尽管我可能不太了解 ZipArchive 如何制作 zips...

如何从字符串转到压缩文件指针,以便将压缩文件通过 ftp 传输到其他服务器?请记住,我不能制作任何文件,否则我只会制作 zip 文件,然后将其 ftp 传输过来。

编辑:根据以下 skinnynerd 的建议,我尝试了以下操作

$zip = new ZipArchive();
if($zip->open('php://memory', ZIPARCHIVE::CREATE)) {
  $zip->addFromString('testtext.txt','Hello World!');
  $zip->close(); 

  $fp = fopen('php://memory','r+');
  fseek($fp,0,SEEK_SET);

  //connect to ftp
  $upload = ftp_fput($conn_id,"upload/transfer/helloworld.zip",$fp,FTP_BINARY);
}

这确实会创建一个 zip 并将其发送过去,但 zip 的大小为 0 字节,因此我认为 'php://memory' 的工作方式与我想的不一样……它实际上在关闭步骤中失败了—— $zip->close() 返回 false,这让我想知道我是否可以将 zips 打开到 'php://memory' 中。有谁知道我可以按照这些方法尝试获取 zip 吗?

【问题讨论】:

  • 看起来 ZipArchive 不支持保存,除非您关闭。它需要有一个->save() 方法,同时保持文件指针处于活动状态以使其工作。 (然后你会寻找 0 并上传。)我会按照 Parahat Melayev 的建议使用 gzencode()。

标签: php file stream zip ziparchive


【解决方案1】:

$zip->getStream('test') 正在获取用于从存档中提取文件 'test' 的流。由于存档中没有文件'test',因此失败。这不是您要使用的功能。

正如您所说,您要做的是将完成的存档发送到 ftp 服务器。在这种情况下,您需要关闭 zip 存档,然后将 php://memory 作为普通文件重新打开(使用 fopen)以发送它。

我不知道,但您也可以直接将$zip 用作资源,而无需关闭并重新打开文件。

【讨论】:

  • 感谢您的回答,我尝试了一些使用 fopen 的方法,但最后我想我会使用 gziped 字符串解决方案。
【解决方案2】:

我认为您可以尝试直接从 ftp 服务器创建流管道

<?php
    $zip = new ZipArchive();
    if($zip->open('ftp://user:password@ftp.host.com/upload/transfer/helloworld.zip', ZipArchive::CREATE)) 
    {
        $zip->addFromString('testtext.txt','Hello World!');                         
        $zip->close();
    } 
    else 
        print "couldn't open zip file on remote ftp host.";

【讨论】:

  • 我试过了,它没有在服务器上创建 zip 文件。
  • 我也试过这个,但我无法让它工作......如果这意味着什么,它在关闭步骤而不是打开时再次失败。
【解决方案3】:

它必须是 Zip 存档吗?由于您正在尝试节省带宽,因此它也可能是 gzip。

<?php
 $ftp_credentials = "ftp://USER:PASSWORD@HOST/helloworld.gz";
 $gz = gzencode("Hello World!", 9);
 $options = array('ftp' => array('overwrite' => true));
 $stream_context = stream_context_create($options);
 file_put_contents($ftp_credentials, $gz, 0, $stream_context);
?>

【讨论】:

  • 是的,它可能是一个 gzip,尽管这将迫使我更改其他代码中的解压缩步骤,所以如果我能让 zip 版本工作,我更愿意。我会尝试看看我是否可以获得 gzip 解决方案,如果它更容易,那么我可以使用它。
  • 所以我以前对 gzip 不太了解,但看起来 zip 会将多个文件和文件夹一起归档的地方 gzip 解决方案只是对字符串起作用,所以这可以保证工作,因为我已经可以发送一个文件就好了......我想我会采用这个解决方案。非常感谢。
猜你喜欢
  • 2013-10-30
  • 2011-07-16
  • 2015-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多