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

PHP读取ZIP文件中JSON数据及子目录内容问题求助

问题描述

我尝试通过PHP读取远程ZIP文件中的JSON数据,但无法成功获取。现有代码用ZipArchive打开远程ZIP链接,尝试读取index.json,同时需要读取ZIP内Objects文件夹及其子目录下的所有JSON文件。另外我有一段将ZIP解压到FTP后可正常运行的代码,希望能解决直接读取ZIP内所有JSON数据的问题。

现有远程读取代码

$url = 'https://website.com/wb9f4a8e744a1'; // 点击该链接会下载ZIP文件

$z = new ZipArchive();
if ($z->open($url)) {
     $json = $z->getFromName("index.json");
     if ($json) {
            // 解析JSON数组
            $json_array = json_decode($json);
            var_dump($json_array);
     }
}

ZIP文件结构

index.json
Objects/          // 需要读取该文件夹及其子目录下的文件
  2/9/289892.json
  4/z/24522.json
  v/9a/45582.json

解压到FTP后可运行的代码

$data = file_get_contents($url); 
$characters = json_decode($data); 
foreach ($characters as $character) {
    echo $character->label . '<br>';
    $dossier = 'objects/' . $character->file;
    $data2 = file_get_contents($dossier); 
    $characters2 = json_decode($data2, true); 
}
解决方案

1. 排查远程ZIP读取失败原因

ZipArchive::open()直接读取远程URL需要满足两个前提:

  • PHP配置中allow_url_fopen必须开启
  • 服务器支持HTTP流包装器(大部分环境默认支持)

可以添加错误排查代码定位问题:

$url = 'https://website.com/wb9f4a8e744a1';
$z = new ZipArchive();
$openResult = $z->open($url);
if ($openResult !== true) {
    switch ($openResult) {
        case ZipArchive::ER_OPEN:
            echo '无法打开文件';
            break;
        case ZipArchive::ER_READ:
            echo '读取文件错误';
            break;
        case ZipArchive::ER_NOZIP:
            echo '不是有效的ZIP文件';
            break;
        default:
            echo '打开失败,错误码:' . $openResult;
    }
    exit;
}

2. 遍历ZIP内所有JSON文件(含子目录)

如果能成功打开ZIP,可遍历所有条目,筛选出目标文件:

$url = 'https://website.com/wb9f4a8e744a1';
$z = new ZipArchive();

if ($z->open($url) === true) {
    // 读取index.json
    $indexJson = $z->getFromName('index.json');
    if ($indexJson) {
        $indexData = json_decode($indexJson);
        echo 'index.json解析结果:<br>';
        var_dump($indexData);
    } else {
        echo '未找到index.json<br>';
    }

    // 遍历Objects目录下的JSON文件
    echo '<br>Objects目录下的JSON数据:<br>';
    for ($i = 0; $i < $z->numFiles; $i++) {
        $filename = $z->getNameIndex($i);
        // 筛选Objects目录下的.json文件
        if (str_starts_with($filename, 'Objects/') && pathinfo($filename, PATHINFO_EXTENSION) === 'json') {
            $jsonContent = $z->getFromIndex($i);
            if ($jsonContent) {
                $jsonData = json_decode($jsonContent, true);
                echo '<br>文件:' . $filename . '<br>';
                var_dump($jsonData);
            }
        }
    }

    $z->close();
} else {
    echo '无法打开远程ZIP文件';
}

3. 备选方案:先下载ZIP到本地再处理

如果直接远程读取失败,可先将ZIP下载到临时目录,兼容性更好:

$url = 'https://website.com/wb9f4a8e744a1';
$tempZip = tempnam(sys_get_temp_dir(), 'remote_zip');

// 下载ZIP到临时文件
if (copy($url, $tempZip)) {
    $z = new ZipArchive();
    if ($z->open($tempZip) === true) {
        // 读取index.json
        $indexJson = $z->getFromName('index.json');
        if ($indexJson) {
            $indexData = json_decode($indexJson);
            var_dump($indexData);
        }

        // 遍历Objects目录下的JSON
        for ($i = 0; $i < $z->numFiles; $i++) {
            $filename = $z->getNameIndex($i);
            if (str_starts_with($filename, 'Objects/') && pathinfo($filename, PATHINFO_EXTENSION) === 'json') {
                $jsonContent = $z->getFromIndex($i);
                $jsonData = json_decode($jsonContent, true);
                var_dump($jsonData);
            }
        }

        $z->close();
    }
    // 删除临时文件
    unlink($tempZip);
} else {
    echo '无法下载远程ZIP文件';
}

4. 适配解压后代码的逻辑

如果要沿用解压后代码的逻辑(通过index.json里的file字段找对应文件),可直接在ZIP内读取对应路径:

$url = 'https://website.com/wb9f4a8e744a1';
$z = new ZipArchive();

if ($z->open($url) === true) {
    $indexJson = $z->getFromName('index.json');
    if ($indexJson) {
        $characters = json_decode($indexJson);
        foreach ($characters as $character) {
            echo $character->label . '<br>';
            // 注意ZIP内路径大小写敏感,要和实际目录名保持一致
            $filePath = 'Objects/' . $character->file;
            $jsonContent = $z->getFromName($filePath);
            if ($jsonContent) {
                $characters2 = json_decode($jsonContent, true);
                var_dump($characters2);
            } else {
                echo '未找到文件:' . $filePath . '<br>';
            }
        }
    }
    $z->close();
}

注意:ZIP内的路径大小写敏感,要和实际ZIP中的Objects/保持一致,解压后代码用的objects/是小写,可能是因为FTP服务器不区分大小写,但ZIP内是严格区分的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 18:45:20