PHP 解析文件功能 - 保存到数据库

PHP parse files function - Save to DB

我今天大部分时间都在做这个,所以我通常在迭代和使用 keys/values 方面取得成功。这一次看起来并不容易,运行 在 php 文档和尾随差异源之间来回切换,运气不好,但这已经很接近了。

所以在这段代码中,我们检查 ../../uploads 所有 *.torrent 文件,解析每个文件并保存为 BLOB = > 数据库.

该代码非常适合个人上传。所以我决定将它们全部循环在一起,并根据它们的 DB ID / FILE ID(全部匹配)将所有文件发送到数据库。所以逻辑很简单。

这是我的代码

// Start parsing files => DB => LONGGLOB
foreach (glob("../../uploads/*.torrent") as $filename) {
    
    // Match file ID with database ID (WHERE CLAUS)
    $fileid = str_replace('.torrent', '', $filename);
    $filename1 = str_replace('../../uploads/', '', $filename);
    
    $fp = fopen('../../uploads/'.$filename1, 'rb');
    //$fp = fopen($_FILES['torrent']['tmp_name'], 'rb');
    $data = '';
    while (!feof($fp)) {
        $data .= fread($fp, 8192);
    }
    fclose($fp);

    $arr = bdecode($data);
    if ($arr === false) {
        die('invalid torrent');
    }

    // TODO: more validity checks for torrent?
    
    if (!array_key_exists('info', $arr)) {
        die('invalid torrent');
    }

    $arr['info']['private'] = 1;

    $infobc = bencode($arr['info']);
    if ($infobc === false) {
        die('bencoding error');
    }

    $info_hash = sha1($infobc);
    $total_size = 0;

    if (array_key_exists('files', $arr['info'])) {
        foreach ($arr['info']['files'] as $file) {
            if (array_key_exists('length', $file)) {
                $total_size += $file['length'];
            }
        }
    } else if (array_key_exists('length', $arr['info'])) {
        $total_size += $arr['info']['length'];
    }
    
    $description = 'dsfsdfDESCR';
    $name = 'dsfsdfNAME';

    // BEncode data and send it to DB
    $data = bencode($arr);
    $an = array_key_exists('anonymous', $_POST);
    $db->query_params("UPDATE torrents SET user_id = :user_id, name = :name, descr = :description, anon = :anonymous, data = :data, info_hash = :info_hash, size = :total_size WHERE torrent_id = :torrentid", array('user_id' => $_SESSION['user']['user_id'], 'name' => $name, 'description' => $description, 'anonymous' => $db->encode_bool($an), 'data' => $data, 'info_hash' => $info_hash, 'total_size' => $total_size, 'torrentid' => $fileid)) or die('db error');
}

我终于让它循环播放每个文件了。但现在的问题是它显示了第一个文件,但它没有继续并实际逐个文件地解析文件(最低 ID => 最高 ID,任一顺序),在雪球效应中产生错误。

我已经做了很多很多尝试,一直到对 fopen() 第一个参数的抱怨,所以我修复了它,现在它没有正确迭代。我相信这是我的逻辑,但我无法理解。

所以 $data = bencode($arr) 需要解析每个图元文件并发送它,因为它与注释掉的上传表单完美配合 ($fp)。感谢任何帮助。

我已经使用所有不同的方法列出了文件,这次是 blob 函数。如何迭代每个文件并解析它 => 下一个文件??

评论部分非常有效。但是我们需要解析每个文件的id。

又自己回答了一个。我必须在最后一个选项中停止 运行,无论如何,这是为需要它的人提供的解决方案。一个小时后我收到了,非常感谢php.net!

解决方案:

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $dir = new DirectoryIterator('../../uploads');
    foreach ($dir as $fileinfo) {
        if (!$fileinfo->isDot()) {
            $getthelist = $fileinfo->getFilename();
            $fp         = fopen('../../uploads/' . $getthelist, 'rb');
            $data       = '';
            while (!feof($fp)) {
                $data .= fread($fp, 8192);
            }
            fclose($fp);
            $arr = bdecode($data);
            if ($arr === false) {
                die('invalid torrent');
            }
            if (!array_key_exists('info', $arr)) {
                die('invalid torrent');
            }
            $arr['info']['private'] = 1;
            $infobc                 = bencode($arr['info']);
            if ($infobc === false) {
                die('bencoding error');
            }
            $info_hash  = sha1($infobc);
            $total_size = 0;
            if (array_key_exists('files', $arr['info'])) {
                foreach ($arr['info']['files'] as $file) {
                    if (array_key_exists('length', $file)) {
                        $total_size += $file['length'];
                    }
                }
            } else if (array_key_exists('length', $arr['info'])) {
                $total_size += $arr['info']['length'];
            }
            $fileid = str_replace('.torrent', '', $getthelist);
            $data   = bencode($arr);
            $an     = array_key_exists('anonymous', $_POST);
            DB::run("UPDATE torrents SET data = :data, info_hash = :info_hash, size = :total_size WHERE torrent_id = :torrentid", array(
                'data' => $data,
                'info_hash' => $info_hash,
                'total_size' => $total_size,
                'torrentid' => $fileid
            )) or die('db error');
        }
    }
}

DirectoryIterator() 就是这里的答案。虽然其他方法有效,但它们不如这种方式有效或合乎逻辑。它按预期完美运行。