【发布时间】:2021-04-30 16:11:25
【问题描述】:
PHP v7.4.16
我有一个相当基本的流过滤器(它扩展了 php_user_filter),我用它来规范化 CSV 文件,因为它们被传输到另一个目的地(在这种情况下使用流包装器的 s3 存储桶)。
filter()函数的内容:
while ($bucket = stream_bucket_make_writeable($in)) {
// Replace any CRLF Windows line-endings with *nix \n
$bucket->data = preg_replace('~(*BSR_ANYCRLF)\R~', "\n", $bucket->data);
$encoding = mb_detect_encoding($bucket->data, mb_detect_order(), true);
$bucket->data = strtolower($encoding) != "utf-8"
? iconv($encoding, "utf-8//IGNORE", $bucket->data)
: $bucket->data;
$consumed += $bucket->datalen;
// Send bucket to downstream brigade
stream_bucket_append($out, $bucket);
}
// Return the code that indicates that the userspace filter returned buckets in $out
return \PSFS_PASS_ON;
我可以像这样成功使用过滤器:
private function streamFileToS3($file_entity) {
$source = fopen($file_entity->local_path, 'r');
$dest = fopen($file_entity->s3_path, 'w');
@\stream_filter_prepend($dest, 'csv', STREAM_FILTER_WRITE);
$chunk_size = (10 * 1024 * 1024);
while (!feof($source)) {
$chunk = fread($source, $chunk_size);
fwrite($dest, $chunk);
}
fclose($dest);
fclose($source);
return true;
}
现在是重要的一点。
将过滤器附加到我要写入的文件句柄时,脚本会使用我期望的内存。
@\stream_filter_prepend($dest, 'csv', STREAM_FILTER_WRITE);
但是当我尝试在文件句柄上使用过滤器时,我正在读取来自:
@\stream_filter_prepend($source, 'csv', STREAM_FILTER_READ);
memory_get_usage() 的输出每次迭代都会增加 fread() 块的大小。
有谁知道这是为什么,有什么办法可以解决吗?
提前致谢
【问题讨论】:
-
您好,我以稍微不同的方式遇到了这个问题,但仍然涉及内存限制。我的解决方案是使用这个包:github.com/box/spout。你需要启用几个扩展,遗憾的是你需要稍微修改你的工作流程。
-
嗨@Ballard,不幸的是,我不确定这是否能解决我的特定用例,但感谢您提及,我没有遇到过这个库。
-
能否请您详细说明您所期望的差异,因为到目前为止我从中得到的是您的内部缓冲区已耗尽,您可以尝试在每次操作后刷新以避免内存泄漏可能跨度>