对于在未来搜索中输入此线程的任何人:
我尝试使用 Hamlet 的关于使用 stream_filter_append 的答案,但注意到我的一些机器在使用此解决方案时存在问题(fread 返回读取的 0 个字节,尽管流仍处于打开状态且并非所有数据都已被读取。
我遇到了 this thread - 结果是 php 中存在一个用于流缓冲的已知错误。
使用我写这篇文章的线程中的代码,它可能会帮助下一个穿越这些路径的旅行者:
// init $client from S3Client
$client->registerStreamWrapper();
// full s3 path to the file
$gzipUrl = "s3://{$bucketName}/{$filePath}";
$sourceFile = fopen($gzipUrl,'rb');
$targetFile = fopen(sys_get_temp_dir() . '/user_input_import.csv.gz','wb');
stream_copy_to_stream($sourceFile,$targetFile);
fclose($sourceFile);
fclose($targetFile);
copy('compress.zlib://' . sys_get_temp_dir() . '/user_input_import.csv.gz',$tmpFileName);
对于我成功的项目。
,
为了使gzread
正常工作,您必须使用gzopen
打开文件。
但是gzopen
不支持文件流,因此通过此功能,您可以通过提供相应的文件路径来仅打开服务器上的文件。
在您的情况下,解决方案是使用压缩过滤器。
因此,您必须使用fopen
来打开文件流,然后应用压缩流过滤器才能读取.gz解码的数据。
stream_filter_append(
$stream,'zlib.inflate',STREAM_FILTER_READ,["window" => 32]
);
有关更多信息,请参阅文档:
https://www.php.net/manual/en/filters.compression.php
很遗憾,上面的文档中没有有关window
参数的信息。以下是 zlib.h inflateInit2文档中的一些有用信息:
windowBits参数是最大值的底两个对数
窗口大小(历史缓冲区的大小)。它应该在
此库版本的范围为8..15。默认值为
如果使用inflateInit,则为15。
...
对于可选的gzip解码, windowBits也可以大于15。
将32位添加到windowBits以启用zlib和gzip解码
自动标头检测,或添加16以仅解码gzip
格式(zlib格式将返回Z_DATA_ERROR)。如果是gzip
流正在解码,strm-> adler是CRC-32而不是
阿德勒32。与gunzip实用程序和gzread()不同(请参见下文),
inflate()不会自动解码串联的gzip流。
inflate()将在gzip流的末尾返回Z_STREAM_END。的
状态需要重置才能继续解码后续的gzip
流。
基于此信息,我建议使用窗口大小32,因为此大小将支持具有自动标头检测功能的zlib和gzip解码。
因此最终代码应如下所示:
$s3 = new S3Client([
'version' => 'latest','region' => 'us-east-2','credentials' => [
'key' => '','secret' => '',],]);
$s3->registerStreamWrapper();
if ($stream = fopen('s3://bucket/file.csv.gz','r')) {
stream_filter_append(
$stream,["window" => 32]
);
// While the stream is still open
while (!feof($stream)) {
// Read 1024 bytes from the stream
$d = gzread($stream,1024);
var_dump($d);
}
// Be sure to close the stream resource when you're done with it
fclose($stream);
}
本文链接:https://www.f2er.com/2021002.html