Всем привет. Я пишу эксплорер файлов(как я уже говорил, зачем он мне нужен я не знаю, мне просто захотелось его сделать). На данный момент реализовано следующее: Вывод файлов, с иконками под их расширение(или с иконкой unknown, если расширение нам неизвестно). Сортировка файлов и папок: сначала идут папки, а потом файлы*(если файлов и папок много - выполняется долго). Определение размера папок*(когда скрипт натыкается на папку с большим объёмом - выполняется долго). Корректное скачивание файлов. Рабочая кнопка "Вверх" - возврат к предыдущей директории Ну и симпатичный интерфейс *-требуется в оптимизации. Какие у меня мысли: Думаю скрипт ускорится если файловую систему связать с БД, и выполнять сортировку там, но всё время придется сверять с БД присутствие/отсутствие тех или иных файлов/директорий. Плюс этого метода в том что если какой-нибудь файл или папка будут отсутствовать или появятся новые - придется делать сортировку единожды, а не всё время. Как быть с определением размера папок - пока не придумал, но тоже что-то с БД буду делать(наверное). Ну многое из того что я хочу реализовать ещё, связано только с дизайном(красивое переименование файлов, создание папок, перемещение файлов etc.) А вот ещё, хочу сделать поиск файлов(и по-этому всё больше склоняюсь к БД =) ) ну всё остальное по пути... P.s. Я не прошу что-то делать за меня, а только подсказать, где-то указать на ошибки и т.д. Скрипт выкладывать? :roll:
Скрипт: PHP: <?php /** * Выполняет вывод всех файлов и каталогов из папки * * @param string $dirn */ $faili=array(); function read_dir($dirn){ global $faili; $dir=@opendir($dirn); while($f=@readdir($dir)){ @array_push($faili,$f); } } $sizes=0; /** * Получает расширение $filename * * @param string $filename * */ function getExten($filename) { return end(explode('.',$filename)); } /** * Вычисляет размер подкаталогов в каталоге * * @param string $dirn */ function size_dir($dirn){ global $sizes; $fails=array(); $dir=@opendir($dirn); while($f=@readdir($dir)){ @array_push($faili,$f); if(($f==".")||($f=="..")){ continue; }else { if (is_file("$dirn/$f")){ $sizes+=filesize("$dirn/$f"); }elseif (is_dir("$dirn/$f")){ size_dir("$dirn/$f"); } } } @closedir($dir); } /** * Округляет размер файла * * @param int $size * @return array * */ function get_ext($size) { $extencion=array('B', 'Kb', 'Mb', 'Gb', 'Tb'); $ext=array(); if (round($size/1125899906842624,2)>=1){ $ext[0]=round($size/1125899906842624,2); $ext[1]=$extencion[4]; }elseif (round($size/1099511627776,2)>=1){ $ext[0]=round($size/1099511627776,2); $ext[1]=$extencion[4]; }elseif (round($size/1073741824,2)>=1){ $ext[0]=round($size/1073741824,2); $ext[1]=$extencion[3]; }elseif (round($size/1048576,2)>=1){ $ext[0]=round($size/1048576,2); $ext[1]=$extencion[2]; }elseif (round($size/1024,2)>=1){ $ext[0]=round($size/1024,2); $ext[1]=$extencion[1]; }elseif (round($size/1024,2)<1){ $ext[0]=round($size/1024,2); $ext[1]=$extencion[1]; } return $ext; } $dirn=dirname (__FILE__); if (isset($_GET['dir'])){ $_GET['dir']=preg_replace("/\\\/","/",$_GET['dir']); /* $_GET['dir']=preg_replace("#\//#i","/",$_GET['dir']); $_GET['dir']=preg_replace("#C:/#i","L:/",$_GET['dir']); $_GET['dir']=preg_replace("#K:/#i","L:/",$_GET['dir']); $_GET['dir']=preg_replace("#E:/#i","L:/",$_GET['dir']);*/ $_GET['dir']=preg_replace("#WM ключи#","/",$_GET['dir']); if (is_file($_GET['dir'])){ $ctl=strlen($_GET['dir']); $ct=substr($_GET['dir'],$ctl-5,5); $ct=str_replace(".","",$ct); header('Content-type: application/'.$ct); $ct=end(explode('/',$_GET['dir'])); header('Content-Disposition: attachment; filename="'.$ct.'"'); echo file_get_contents($_GET[dir]); exit(); }else { $dirn=$_GET['dir']; } } /** * Получает строку $string урезает ее до $numsymbol начиная с $start * и доставляет в конец строки $symbol * * @param string $string * @param int[optional] $numsymbol * @param string $symbol * @param int[optional] $start * @return string */ function strlengh($string, $numsymbol=7,$symbol=" ...",$start=0){ if (strlen($string)>$numsymbol) { $string=substr ($string, $start, $numsymbol)."$symbol"; }elseif (strlen($string)<$numsymbol) { $string=substr ($string, $start,$numsymbol); } return $string; } $dirn=preg_replace("/\\\/","/",$dirn); read_dir($dirn); $dirn=preg_replace("#\//#","/",$dirn); $vivod=""; /* Методом сортировки приводим к виду: "Сначала папки, потом файлы" */ for ($j=0; $j<count($faili);$j++){ for ($i=0; $i<count($faili)-1;$i++){ if (is_dir($dirn.'/'.$faili[$i+1])) { $k=$faili[$i+1]; $faili[$i+1]=$faili[$i]; $faili[$i]=$k; //прекращаем сортировку если файлов и папок больше 100, дабы не зависать. if ($i>100){ break; } } } } for ($i=0; $i<count($faili);$i++){ $sizes=0; if (preg_match("/^\.\.|\.$/",$faili[$i])){ /* $faili[$i]=preg_replace("/^\.\.$/","Назад",$faili[$i]); $vivod.="<img src=http://i045.radikal.ru/0907/07/159b640fe36b.png> <a href=\"explorer.php?dir=$dirn/..\"><font color=\"black\">$faili[$i]</font></a><br>" ;*/ continue; } if (is_dir($dirn.'/'.$faili[$i])){ //временно убрано вычисление размеров папок /* if(($faili[$i]!=".")){ size_dir($dirn.'/'.$faili[$i]); $sizes=get_ext($sizes); }*/ $vivod.="<a href=\"explorer.php?dir=$dirn/$faili[$i]\" title=\"$faili[$i]\"><font color=\"black\"><div style=\"float : left; height : 75px; width : 15%; border : solid 0px Aqua\"><img src=\"img/Extencions/Folder-close.png\" /><br> ".strlengh($faili[$i],15,"...")."</font></a></div>" ; } else{ $extfiles[$i]=$faili[$i]; $file_ext[$i]=getExten($extfiles[$i]); $sizes=get_ext(filesize("$dirn/$faili[$i]")); if (is_file("img/Extencions/".$file_ext[$i].".png")){ $vivod.="<a href=\"explorer.php?dir=$dirn/$faili[$i]\" title=\"$faili[$i]\"><font color=\"#6699cc\"><div style=\"float : left; width : 15%; height : 75px; border : solid 0px Aqua\"><img src=\"img/Extencions/".$file_ext[$i].".png\" /><br> ".strlengh($faili[$i],15,"...")."</font></a></div>" ; } else { $vivod.="<a href=\"explorer.php?dir=$dirn/$faili[$i]\" title=\"$faili[$i]\"><font color=\"#6699cc\"><div style=\"float : left; width : 15%; height : 75px; border : solid 0px Aqua\"><img src=\"img/Extencions/unknown.png\" /><br> ".strlengh($faili[$i],15,"...")."</font></a></div>" ; } } } $back=dirname($dirn); $content=file_get_contents('index.htm'); $content=preg_replace('/{FOLDER}/',$dirn,$content); $content=preg_replace('/{CONT}/',$vivod,$content); $content=preg_replace('/{GO_BACK}/',"explorer.php?dir=$back",$content); echo $content; ?> Шаблон: HTML: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Explorer</title> <link href="css/main.css" type="text/css" rel="Stylesheet" /> <script type="text/javascript" src="jquery-1.3.2.min.js"></script> <script type="text/javascript"> var showing="hidden"; function show_menu(id){ if (showing == "hidden") { $('#' + id).fadeTo(250, 1); showing = "show"; }else if(showing=="show"){ $('#' + id).fadeTo(250, 0); showing='hidden'; } } function hide_menu(id){ $('#'+id).fadeTo(250,0); showing='hidden'; } </script> </head> <body> <div class="wrapper"> <div class="title"> <img src="img/siteElements/header/folder_icon.png" /> {FOLDER} </div> <div class="icon_panel_top"> </div> <hr class="hr_divider" /> <div class="icon_panel_bottom"> <a href="javascript:void(0)" class="a_img"><img src="img/siteElements/header/arrow_back.png" /></a> <a href="javascript:void(0)" class="a_img"><img src="img/siteElements/header/arrow_forward.png" /></a> <img src="img/siteElements/header/panel_divider.png" /> <a href="{GO_BACK}" class="a_img"><img src="img/siteElements/header/folder_up.png" /></a> <a href="javascript:show_menu('block1')" class="a_img"><img src="img/siteElements/header/search.png" /></a> <a href="javascript:void(0)" class="a_img"><img src="img/siteElements/header/folders.png" /></a> </div> <hr class="hr_divider" /> <div class="adress_bar"> <form> Адрес: <select class="text_adress_bar"> <option>1</option> </select> <a href="javascript:void(0)" class="a_img"><img src="img/siteElements/header/goto.png" /></a> </form> </div> <hr class="hr_divider" /> <div class="left_panel"> <div id="block1" class="l_block"> <div class="h_blocks" >Поиск <span style="cursor: pointer;" onclick="hide_menu('block1')">[X]</span></div> <div class="ic_cblock"><br> <input type="hidden" id="patch" value="{PATCH}"> <form action="" method="POST" id="search"> <input type="text" id="keywords"> <input type="button" value="Поиск"> </form><br> </div> </div> </div> <div class="right_panel">{CONT}</div> </div> </body> </html>
Вопрос в следующем: стОит ли связывать фс с бд, и возможно ли ещё оптимизировать мой код в некоторых моментах. Да и вообще интересно было послушать от "дедов" какую-нибудь критику, или предложения =)
PHP: <? for ($j=0; $j<count($faili);$j++){ for ($i=0; $i<count($faili)-1;$i++){ if (is_dir($dirn.'/'.$faili[$i+1])) { $k=$faili[$i+1]; $faili[$i+1]=$faili[$i]; $faili[$i]=$k; //прекращаем сортировку если файлов и папок больше 100, дабы не зависать. if ($i>100){ break; } } } } ?> Сортировка проходит очень долго если файлов много (много это не 1000000000+ файлов, а хотябы 400) PHP: <? function size_dir($dirn){ global $sizes; $fails=array(); $dir=@opendir($dirn); while($f=@readdir($dir)){ @array_push($faili,$f); if(($f==".")||($f=="..")){ continue; }else { if (is_file("$dirn/$f")){ $sizes+=filesize("$dirn/$f"); }elseif (is_dir("$dirn/$f")){ size_dir("$dirn/$f"); } } } @closedir($dir); } ?> аналогичная ситуация, если файлов в папке много, то грузится очень-очень долго. есть варианты как можно оптимизировать?
xDamneDx Сортировка проходит очень долго постарайся привести код к использованию готовых функций пхп для сортировки массивов. Они написаны на сях и работают быстро. А что ты там делаешь - это конечно смерть всему живому. xDamneDx есть варианты как можно оптимизировать? вроде как есть. смотри в гугле по "php file listing" или типа того
нууу, не думаю. мне вот какая мысль пришла в голову, а что если просто в самой функции: PHP: <? function read_dir($dirn){ global $faili; $dir=@opendir($dirn); while($f=@readdir($dir)){ @array_push($faili,$f); } } ?> сделать две разных переменные для файлов и папок? а потом просто выводить их, так по-моему даже будет лучше, наааамного лучше.
ну как я и говорил, только что проверил всё верно выводит =) ура =) а вот с размером директорий как быть теперьче...
незнаю, мне показалось что разумнее будет если в самой функции просто разбить на две переменные, дальше будет легче работать(имхо) с папками и файлами отдельно
Вместо opendir и потом readdir в цикле можешь один раз вызвать scandir() и потом в цикле перебирать простой php-массив, который вернёт эта функция. Рекурсивный обход всех вложенных поддиректорий - это полюбому будет сравнительно долго, если их много. Придётся дёргать ФС сервера для просмотра каждой поддиректории и всех её "потомков".
xDamneDx Если тебе нужен Эксплорер, а НЕ СКРИПТ эксплорера, то без индексов далеко не уедешь, поверь. Храни контрольные суммы, индексируй вторичные ноды бинарных деревьев и не сортируй всё каждый раз, так же как и не делай листиг. Хотя если тебе только скрипт написать, который не имеет практического применения, то можно и не думать об этом.
В принципе, мне нужна просто практика, вот и начал реализовывать задумку. Как много новых слов :О хранить контрольные суммы ещё более или менее понятно. (Хранить в БД?) Индексировать вторичные ноды бинарных деревьев...(???тут по-подробней, пожалуйста. Нагуглить мало чего получилось) Не сортировать всё каждый раз(это реализовывается опять же с помощью БД? или я что-то не так понимаю?) З.ы. может я для практики не очень хорошую задумку выбрал? =))))
кстати говоря, сейчас у меня всё происходит так: PHP: <? function read_dir($dirn){ global $faili; global $dirs; $dir=@opendir($dirn); while($f=@readdir($dir)){ if (is_file("$dirn/$f")) { array_push($faili,$f); } else { array_push($dirs,$f); } } } ?> То бишь, я взял две разных переменные и соответственно раскидал папки и файлы в них. Далее двумя циклами последовательно вывожу сначала папки, а потом файлы.