首页 > 解决方案 > PHP:我可以使用内置的 curl 函数通过 gunzip 管道 curl 输出吗?

问题描述

我正在编写一个脚本,该脚本下载大文件,解压缩它们,然后解析内容,将我喜欢的数据插入到 sql 中。我将此脚本升级为以多线程类型的方式工作,它可以同时下载一个文件、解压缩另一个文件并解析另一个文件。但是,唉,我遇到了硬盘驱动器的瓶颈。

在 的帮助下##php,我意识到我可以使用以下命令将输出curl直接通过管道传输gunzip到将我的磁盘 i/o 减半(不包括 SQL):

卷曲https://example.com/path/to/large_file.gz | gunzip -c > /large_temp_files/large_file

经测试证实,该方法将未压缩的数据直接写入磁盘,无需先写入压缩数据。

所以我的问题是,有什么方法可以像使用 php 的内置curl函数那样管道数据?

对于常规文件,您可以打开文件指针并将该指针设置为curl_setopt选项之一,以将文件下载到磁盘而不是将数据设置为变量。

这些是 5 GB 的文件,因此无法正常工作。我的所有其他代码都为我的 http 请求使用内置函数,所以如果可能的话,我想坚持这样做,以保持一致性和可读性。

标签: phpcurllibcurlphp-curl

解决方案


我实际上并没有对此进行测试,但我认为这可以通过使用带有 inflate_init() 和 co 的自定义 CURLOPT_WRITEFUNCTION 来实现,例如

$decompressor = inflate_init(ZLIB_ENCODING_DEFLATE);
$fp = fopen("decompressed", "wb");
$ch = curl_init("http://url.com/large_file.zip");
curl_setopt_array($ch, array(
    CURLOPT_WRITEFUNCTION => function ($ch, string $compressed) use (&$fp, &$decompressor) {
        fwrite($fp, inflate_add($decompressor, $compressed));
        return strlen($compressed);
    }
));
curl_exec($ch);
curl_close($ch);
fclose($fp);
unset($fp,$ch,$decompressor); // don't know how to clean up the decompressor, hopefully GC will do it.

顺便说一句,如果您想真正花哨,您可以直接从 deflate_add() 调用解析数据并将其插入到您的 SQL 数据库中,而无需将解压缩的数据写入磁盘,这可能更快(与从硬盘驱动器读取相比,从 ram 读取非常快 :) )


推荐阅读