大型站点中使用PHP的所有文件列表
我需要从另一台服务器列出一台服务器上的所有文件 我无法访问PHP配置,比如远程服务器的最大超时。 最大超时时间可能非常短,如30秒。在某些情况下,以下代码会出现超时问题,因为迭代器没有足够的时间获取所有文件大型站点中使用PHP的所有文件列表,php,Php,我需要从另一台服务器列出一台服务器上的所有文件 我无法访问PHP配置,比如远程服务器的最大超时。 最大超时时间可能非常短,如30秒。在某些情况下,以下代码会出现超时问题,因为迭代器没有足够的时间获取所有文件 public function getStructure($path) { $structure = new \stdClass(); $structure->dirs = array(); $structure->file
public function getStructure($path)
{
$structure = new \stdClass();
$structure->dirs = array();
$structure->files = array();
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path), \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file)
{
if ($file->isDir())
{
$structure->dirs[] = $file->getRealpath();
}
else
{
$structure->files[] = $file->getRealpath();
}
}
return $structure;
}
我正在寻找一种在多个调用中获取结构的方法。类似于:myremotesite.com/api/v1/structrue?start=xxxx,其中start是最后一个调用停止的点
感谢您的帮助听起来您需要一个具有保存/恢复功能的目录。。。我可能会在SQLite中实现它,因为默认情况下它是同步的 因为我很无聊。。未经测试,但应在理论上可行。不要试图对这段代码实施beginTransaction()/commit()优化,这将破坏整个代码的“同步并允许随时崩溃”部分
<?php
//will return bool(true) when it's finished creating the database.
//should be timeout/unstable system resistant,
//relying on SQLite's syncronous-by-default nature.
function dirToSQLite($dir,$sqldb){
if(!is_readable($dir)){
throw new InvalidArgumentException('argument 1 must be a readable dir, but is not readable.');
}
if(!is_dir($dir)){
throw new InvalidArgumentException('argument 1 is not a valid dir');
}
$db=new PDO('sqlite:'.$sqldb,'','',array(PDO::ATTR_EMULATE_PREPARES => false,PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$db->exec('CREATE TABLE IF NOT EXISTS `dir` (`id` INTEGER PRIMARY KEY,`path` TEXT UNIQUE,`type` TEXT);');
$db->query('INSERT OR IGNORE INTO `dir` (`path`,`type`) VALUES('.$db->quote($dir).',\'dirUnexplored\');');
$stm=$db->prepare('INSERT INTO `dir` (`path`,`type`) VALUES(:path,:type);');
$stmExplored=$db->prepare('UPDATE `dir` SET `type` = \'dir\' WHERE id = ? ');
$path='';
$type='';
$stm->bindParam(':path',$path,PDO::PARAM_STR);
$stm->bindParam(':type',$type,PDO::PARAM_STR);
while(true){
$found=false;
foreach($db->query('SELECT `id`,`path` FROM `dir` WHERE `type` = \'dirUnexplored\'') as $res)
{
$found=true;
$di=new DirectoryIterator($res['path']);
foreach($di as $file){
if($file->isDot()){
continue;
} else
if($file->isLink()){
$type='link';
} else
if($file->isDir()){
$type='dirUnexplored';
} else
if($file->isFile()){
$type='file';
} else
{
$type='unknown';
}
$path=$file->getPathname();
$stm->execute();
}
$stmExplored->execute(array($res['id']));
}
if(!$found){
break;
}
}
return true;
}
if(true===dirToSqlite('/home/foo','homefoo.db3')){
echo "finished!";
}else {
throw new Exception();
}
ini\u集('max\u execution\u time',1000)
@riggsfully很确定他使用的是一个愚蠢的共享托管服务,它不允许编辑执行时间。(事实上,他们中的许多人运行一个守护进程,该守护进程会持续监视php脚本,并在任何运行超过30秒的php脚本上运行kill-s SIGKILL pid
。(Byetost,000webhost,freewebhost.com等)见鬼,即使是一些付费主机提供商也会这样做,比如proisp.noThank,因为我说过我没有访问远程服务器的配置权限。这就是为什么我要寻找一个完整的PHP解决方案。所有ini_集(**)也被锁定。没有办法让目录迭代器从特定的“位置”开始(由于目录内容或多或少是以随机顺序返回的,这也没有多大意义。)使用这种方法,您最多可以通过在循环中保留一个计数器来“忽略”前X个条目,然后只对之后的文件执行“昂贵”的操作(is_dir,getRealPath)。(加上打破循环,在一轮中你想要处理的条目数被处理后。)谢谢,这是一个非常聪明的方法。我已经有MySQL访问,所以我将使用它。