You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中通过流式处理解压S3中的大Zip文件?

PHP流式解压S3中大型Zip文件的可行方案

PHP完全支持流式解压处理,不需要把整个Zip文件下载到本地或全量加载到内存,能边下载、边解压、边上传到S3,完美适配Lambda的资源限制,不用额外升级Vapor资源。

核心实现思路

主要依赖PHP的原生扩展或轻量第三方库,结合AWS SDK的流式API,实现"分段处理":

  • 从S3流式拉取Zip文件的分片内容,而非一次性下载完整文件
  • 解析Zip流,直接定位并读取内部的JSON文件流
  • 将解压后的JSON流直接上传回S3,全程内存占用可控

原生PHP + AWS SDK 实现(Laravel环境)

这是最贴合Laravel Lambda场景的方案,无需额外引入第三方库:

use Aws\S3\S3Client;
use ZipArchive;

// 初始化S3客户端(Laravel环境也可直接用Storage门面)
$s3 = app('aws')->createClient('s3');

// 配置源文件和目标文件的S3路径
$sourceBucket = 'your-source-bucket';
$sourceKey = 'path/to/large-archive.zip';
$targetBucket = 'your-target-bucket';
$targetKey = 'path/to/uncompressed.json';

// 创建临时内存流存储Zip分片内容(内存不足时自动转临时文件)
$zipTempStream = fopen('php://temp', 'r+');

// 从S3流式拉取Zip文件,边拉边写入临时流
$s3->getObject([
    'Bucket' => $sourceBucket,
    'Key' => $sourceKey,
    'Callback' => function ($chunk) use ($zipTempStream) {
        fwrite($zipTempStream, $chunk);
        fflush($zipTempStream);
    },
]);

// 重置临时流指针到开头
rewind($zipTempStream);

$zip = new ZipArchive();
// 通过zip://协议打开内存中的Zip流
if ($zip->open('zip://' . stream_get_meta_data($zipTempStream)['uri']) === true) {
    // 假设Zip内只有一个JSON文件,若有多个可遍历getNameIndex定位
    $jsonEntryName = $zip->getNameIndex(0);
    
    // 获取Zip内JSON文件的流
    $jsonStream = $zip->getStream($jsonEntryName);
    
    // 直接把JSON流上传到S3,无需落地本地
    $s3->putObject([
        'Bucket' => $targetBucket,
        'Key' => $targetKey,
        'Body' => $jsonStream,
    ]);
    
    $zip->close();
}

fclose($zipTempStream);

注意事项

  • 确保Lambda执行角色拥有S3的GetObject和PutObject权限
  • 如果Zip内有多个文件,可通过循环$zip->numFiles遍历getNameIndex找到目标JSON
  • php://temp默认内存阈值是1MB,超过后会自动切换到Lambda的临时存储(/tmp),但流式处理下内存占用极低
  • 若用Laravel的Storage门面,可替换S3客户端的初始化,代码更简洁

替代方案:PhpZip库(纯PHP实现)

如果原生ZipArchive在某些环境下有兼容性问题,可使用PhpZip纯PHP库,它对流式处理的支持更灵活:

use PhpZip\ZipFile;
use Aws\S3\S3Client;

$s3 = app('aws')->createClient('s3');
$zipTempStream = fopen('php://temp', 'r+');

// 先从S3拉取Zip到临时流(同上面的代码)
$s3->getObject([
    'Bucket' => $sourceBucket,
    'Key' => $sourceKey,
    'Callback' => function ($chunk) use ($zipTempStream) {
        fwrite($zipTempStream, $chunk);
        fflush($zipTempStream);
    },
]);
rewind($zipTempStream);

$zipFile = new ZipFile();
$zipFile->openStream($zipTempStream);

// 遍历Zip内的文件,找到JSON文件
foreach ($zipFile->getEntries() as $entry) {
    if (pathinfo($entry->getName(), PATHINFO_EXTENSION) === 'json') {
        $jsonStream = $entry->getInputStream();
        $s3->putObject([
            'Bucket' => $targetBucket,
            'Key' => $targetKey,
            'Body' => $jsonStream,
        ]);
        break;
    }
}

$zipFile->close();
fclose($zipTempStream);

内容的提问来源于stack exchange,提问作者Thomas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:05:24