Как вывести каталог с большим количеством файлов в php? - PullRequest
0 голосов
/ 06 ноября 2018

Я знал, что это когда-нибудь случится ... Так что у меня есть процедура php, чтобы вывести список файлов в каталоге, получить свойства и подкаталоги и вернуть вызов http с хорошей строкой json со всей информацией. На моем локальном хосте я использую его для рекурсивного перечисления всех файлов в каталоге и подкаталогах, поэтому у меня будет общее количество байтов и т. Д. Это часть кода, которая фактически перечисляет файлы:

        (...)
        $this->Lista = array();
        $this->SubDirs = array();
        $ldPont  = opendir($dir);
        if(!$ldPont){
            $this->erro = 'perms';
            return FALSE;
        } else {
            $this->tamanho = 0;
            $this->tamanhoTotal = 0;
            while(FALSE !== ($ldNome = readdir($ldPont))) {
                if(substr($ldNome, 0, 1)!="." && substr($ldNome, 0, 2)!=".."){
                    //echo('<p>'.$ldNome.'</p>');
                    if(is_dir($dir.'/'.$ldNome)){
                        $this->SubDirs[] = $this->elementoDoArquivo($dir.'/'.$ldNome);
                    } else {
                        $path = $dir.'/'.$ldNome;
                        $this->tamanhoTotal += filesize($path);
                        $ldBase = pathinfo($path, PATHINFO_FILENAME);
                        $ldExt = pathinfo($path, PATHINFO_EXTENSION);
                        $ldExt = strtolower($ldExt);
                        if(is_array($Exts) && count($Exts)>0){
                            $ldTeste = in_array($ldExt, $Exts);
                        } else {
                            $ldTeste = TRUE;
                        }
                        if($ldTeste) {
                            $Arq = $this->elementoDoArquivo($path);
                            if($Arq["Metadados"]) $this->comMetadados = TRUE;
                            $this->Props[$Arq["Prop"]["name"]] = $Arq["Prop"];
                            $this->tamanho += $Arq["bytes"];
                            $this->Lista[] = $Arq;
                        }
                    }
                }
            }
            // Saída de uma leitura ok
            closedir($ldPont);
            uasort($this->Lista, $sort_func[$ord]); //$sort_func[$this->ordem]);
            if($ord_r) $this->Lista = array_reverse($this->Lista);
            $this->Lista = array_values($this->Lista);
            return $this->Lista;
        }

Это класс. Перечисление каталога выполняет много задач, и в конечном итоге на удаленном сервере произойдет тайм-аут с большим количеством файлов, в зависимости от доступности сервера (это общий хостинг). Думаю, мне нужно разобраться с этим по-другому, не знаю как. Есть предложения?

РЕДАКТИРОВАТЬ: я обойти проблему с более легким кодом, который использует glob и не ищу столько деталей каждого файла. С помощью нескольких испытаний я смог получить нужный результат. Но проблема все еще сохраняется ... Код является частью большей библиотеки, вот часть, которую я использовал:

    case "list":
        if(!$usrRead){
            $Res->erro = "perms";
            $Res->msg = "Usuário sem permissões para esse diretório.";
            $Res->descr = $UsrPerms;
            break;
        }
        $Arqs = array();
        $Dirs = array();
        if(!is_dir($dirTeste)){
            $Res->erro = "diretório";
            $Res->msg = "O diretório não existe.";
        } else {
            $Args = explode(",",$nome);
            foreach($Args as $arg){
                if($arg=="") $arg = "*.*";
                $List = glob($dir.$arg);
                foreach($List as $path){
                    if(is_file($path)) {
                        $Arq = array(
                            "nome"=>basename($path), 
                            "datac"=>filectime($path), 
                            "datam"=>filemtime($path), 
                            "bytes"=>filesize($path));
                        if($MetaCampos){
                            $path_meta = nomearqMeta($path);
                            if($path_meta) {
                                $Meta = json_decode(file_get_contents($path_meta));
                                if($Meta) {
                                    foreach($MetaCampos as $campo){
                                        $Arq[$campo] = $Meta->$campo;
                                    }
                                }
                            }
                        }
                        $Arqs[] = $Arq;
                    }
                    //if(is_dir($path)) $Dirs[] = $path;
                }
            }
            if(count($Args)==1) {
                $Dirs = glob($dir."*", GLOB_ONLYDIR);
                $Dirs = array_map(function($d) { return $d."/"; }, $Dirs);
            }
            $Res->arqs = $Arqs;
            $Res->subdirs = $Dirs;
            $Res->erro = "OK";
            $Res->msg = "";
        }
        $Res->descr = "op:list,dir:".$dir.",nome:".$nome.",metaCampos:".$metaCampos;
        break;

1 Ответ

0 голосов
/ 07 ноября 2018

Если вы работаете в Linux, я бы предложил выполнить рекурсивный листинг dir с помощью PHP shell_exec (или exec) и вывести результат в текстовый файл (см. Пример кода ниже). Затем просто file_get_contents () с PHP

<?php

$execListFile = shell_exec('ls -R /your/dir/path/here > mylistofFiles.txt');

$myFiles = file_get_contents('mylistofFiles.txt');

PS: этот код не проверен, но вы поняли.

Ссылки PHP.net shell_exec Команда Linux ls

PS: эквивалент окна ls -R равен dir / s

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...