PHP S3流包装器读取CSV GZ压缩文件

使用aws-php-sdk从s3存储桶中读取csv.gz文件。所有文件都是csv.gz文件,我正在计划读取这些文件,然后将数据导入到我的数据库中。

我看过很多堆栈溢出问题,但似乎无法正常工作。

这是我到目前为止编写的代码。

$s3 = new S3Client([
    'version' => 'latest','region' => 'us-east-2','credentials' => [
        'key' => '','secret' => ''
    ]
]);
$s3->registerStreamWrapper();

if ($stream = fopen('s3://bucket/file.csv.gz','r')) {
    // 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);
}

下面的代码只返回随机字符,必须是压缩文件的内容。

如果有人可以共享一个代码示例,说明如何解压缩csv.gz文件,然后从中读取文件,允许我将其导入数据库,那么我将不胜感激。

iCMS 回答:PHP S3流包装器读取CSV GZ压缩文件

对于在未来搜索中输入此线程的任何人:

我尝试使用 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

大家都在问