PHP

Диспетчер файлов

Диспетчер файлов - он же - файловый менеджер - нужен для управления сайтом. Обычно хостинг предоставляет такую услугу, но бывает и так, что где-то и как-то нашлось на сервере свободное место и можно поставить на это место сайт, но возникает проблема управления. Например, если домен третьего уровня, не стоит расчитывать, что хозяин домена второго уровня предоставит возможность пользоваться своей системой управления и, тем самым, дать доступ к своему домену. Тогда без файлового менеджера не обойтись. Итак, что должен уметь диспетчер файлов в минимальном и, соответственно, самом простом варианте. Первое - открывать каталоги домена сайта и обеспечивать полную навигацию по сайту. Второе - загружать файлы с компьютера на сервер. Третье - создавать и удалять папки и файлы. И четвертое - давать возможность редактировать файлы. Кроме этого, нужно обрабатывать ошибки, другими словами, выводить сообщения о том как завершилась та или иная операция - успешно или нет. Практика показывает, что такого набора функций вполне достаточно для полноценного управления сайтом. Код простого файлового менеджера:

<?php


function out($tp,$arr){
for($i=0;$i<count($arr);$i++){
echo $tp.$arr[$i]."<BR>";
}echo "<BR>";
}

function dir_size($dns) {
$files= scandir($dns);
foreach($files as $file) {
if(($file == ".") || ($file == ".."))continue;
if(is_file($dns."/".$file)) $size += filesize($dns."/".$file);
if(is_dir($dns."/".$file)) $size += dir_size($dns."/".$file); }
if(!$size){$size="<a href=file_manager.php?deld=deld&dir=".$dns.">Удалить</a>";}
else {$size=$size." байт ";}
return $size; }

function upl_file($dn,$fn,$tn){
if(!is_dir($dn)){$inf="Сюда файл не грузится";return $inf;}
if(!is_uploaded_file($tn)||!copy($tn,$dn.chr(47).$fn))
{$inf="Не удалось загрузить файл";}
else {$inf="Файл ".$_FILES['file']['name']." загружён на сервер"; }
return $inf;}

function create_dir($n_d){
if(mkdir($n_d,0777)){$inf="Папка ".$n_d." успешно создана";} else {$inf="Не удалось создать папку ".$n_d;}
return $inf;
}

function create_f($n_f){
if(touch($n_f)){$inf="Файл ".$n_f." успешно создан";} else {$inf="Не удалось создать файл ".$n_f;}
return $inf;
}

function scand($dn){
if(!is_dir($dn))return;
$d = dir($dn);
while($file=$d ->read()) {
if($file==".."||$file==".") continue;
if(is_dir($dn."/".$file)){$fl[0][]= "<a href=file_manager.php?dir=".$dn."/".$file.">".$file."</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".dir_size($dn."/".$file);}
else {$fl[1][]="<a href=file_manager.php?dir=".$dn."/".$file."&fop=2>".$file."</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".filesize($dn."/".$file)." байт "; }
}
$d->close();
return $fl;}

function write_file($data,$rp){
$f = fopen($rp,"w");
if(fwrite($f,$data)){$inf="Изменения сохранены";} else {$inf="Не удалось записать файл";}
fclose($f);
return $inf;
}

$dir=$_GET['dir'];
if(!$dir)$dir=$_POST['dir'];
if(!$dir)$dir=".";
$mode=$_GET['mode'];
$btnd=$_GET['btnd'];
$btnf=$_GET['btnf'];
$btnu=$_POST['btnu'];
$namedir=$_GET['namedir'];
$namef=$_GET['namef'];
$fop=$_GET['fop'];
$btn=$_POST['btn'];
$fc=$_POST['fc'];
$deld=$_GET['deld'];
$del_file=$_GET['del_file'];
$del_f=$_GET['btndel'];
$del_d=$_GET['del_dir'];
$edit=$_GET['edit'];


if($btn=="Сохранить"){$info=write_file($fc,$dir);}
if($btnd)$info=create_dir($dir."/".$namedir);
if($btnf)$info=create_f($dir."/".$namef);
if($btnu)$info=upl_file($dir,$_FILES['file']['name'],$_FILES['file']['tmp_name']);

if($edit==1){$fc=htmlspecialchars(file_get_contents($dir));
$frme="<center><b>Редактирование файла:</b>".$dir."<BR><form name=frm action=file_manager.php method=POST><textarea name=fc rows=24 cols=64 >".$fc."</textarea><BR>
<input type=hidden name=dir value=".$dir."><input type=hidden name=fop value=2><center><input type=submit name=btn value='Сохранить'><input type=submit name=btn value='Закрыть'></center></form></center>";}

if(!$fop){$m=scand($dir);}

$delfile="<form action=file_manager.php ><BR><font color=#ff0000>Файл ".$dir." будет удален! </font><BR><input type=hidden name=dir value=".$dir."><input type=submit name=btndel value='Продолжить'><BR><input type=submit name=btndel value='Выход'>";

$deldir="<form action=file_manager.php ><BR><font color=#ff0000>Папка ".$dir." будет удалена! </font><BR><input type=hidden name=dir value=".$dir."><input type=submit name=del_dir value='Продолжить'><BR><input type=submit name=del_dir value='Выход'>";

if($del_d==Продолжить){if(@rmdir($dir)){$info="Папка ".$dir." удалена";} else{$info="Папку ".$dir." не удалось удалить";}}

if($del_f==Продолжить){if(@unlink($dir)){$info="Файл ".$dir." удален";} else{$info="Файл ".$dir." не удалось удалить";}}

$upl="<form method=POST enctype=multipart/form-data>
<input type=file name=file ><BR>
<input type=submit name=btnu value=Загрузить>
</form>";

$cdr="<form >Имя папки: <BR><input type=text name=namedir ><BR><BR><input type=hidden name=dir value=".$dir."><input type=submit name=btnd value='Создать'>";

$cdf="<form >Имя файлa: <BR><input type=hidden name=dir value=".$dir."><input type=text name=namef ><br><br><input type=submit name=btnf value='Создать'>";

$hmenu="<BR><a href=file_manager.php?mode=1&dir=".$dir.">Загрузить файл</a>&nbsp;&nbsp;<a href=file_manager.php?mode=2&dir=".$dir.">Создать папку</a>&nbsp;&nbsp;<a href=file_manager.php?mode=3&dir=".$dir.">Создать файл</a><BR>";

$fmenu="<BR><a href=file_manager.php?edit=1&dir=".$dir.">Редактировать</a>&nbsp;&nbsp;<a href=file_manager.php?edit=2&dir=".$dir.">Удалить</a>";

$frm[1]=$upl;
$frm[2]=$cdr;
$frm[3]=$cdf;
if($dir=="."){$bk="";}else{$bk="Назад";}
$back=substr($dir,0,strrpos($dir,"/"));
echo "<h3>Диспетчер файлов</h3>".$hmenu.$info."<BR><a href=file_manager.php?dir=".$back.">".$bk."</a><BR>Путь : ".$dir."<BR>";
if($mode){echo $frm[$mode];}
elseif($fop){echo "Файл : ".$dir." ".$fmenu;}
elseif($edit==1)echo $frme;
elseif($edit==2)echo $delfile;
elseif($deld)echo $deldir;
elseif($mode==1)echo $upl;
else {
out("<b>Папка</b> ",$m[0]);
out("<i>Файл</i> ",$m[1]);}
?>

Теперь подробнее. Первым делом опредеяем основные функции. Сначала - функция вывода массива на экран, которой передается сам массив $arr и некий префикс $tp (для оформления, можно и не передавать). Функция выводит все элементы массива, предворяя их префиксом, и после каждого переводит строку:

function out($tp,$arr){
for($i=0;$i<count($arr);$i++){
echo $tp.$arr[$i]."<BR>";
}echo "<BR>";
}

Следующая функция опредяет размер переданной ей директории в байтах:

function dir_size($dns) {
$files= scandir($dns);
foreach($files as $file) {
if(($file == ".") || ($file == ".."))continue;
if(is_file($dns."/".$file)) $size += filesize($dns."/".$file);
if(is_dir($dns."/".$file)) $size += dir_size($dns."/".$file); }
if(!$size){$size="<a href=file_manager.php?deld=deld&dir=".$dns.">Удалить</a>";}
else {$size=$size." байт ";}
return $size; }

Во второй строке получаем имена всех файлов в директории и потом для каждого из них в цикле foreach: 1) определяем, содержится ли в имени файла точка или две точки, если содержатся, то переходим к следующему файлу, 2) если файл является файлом, то определяет его размер в байтах, 3) а если файл является директорией, снова вызываем эту же функцию (такой вызов называется рекуррентным), 4) если директрия пустая, показываем соответствующей ссылкой, что ее можно удалить, 5) а если директория не пустая, добавляем к числу байт слово и 6) возвращаем размер. Теперь функция, загружающая файл на сервер. Ей необходимо передать имя директории, куда будет загружен файл, имя файла и временное имя файла :

function upl_file($dn,$fn,$tn){
if(!is_dir($dn)){$inf="Сюда файл не грузится";return $inf;}
if(!is_uploaded_file($tn)||!copy($tn,$dn.chr(47).$fn))
{$inf="Не удалось загрузить файл";}
else {$inf="Файл ".$_FILES['file']['name']." загружён на сервер"; }
return $inf;}

Во второй строке функции проверяется, является ли указанный адрес директорией, если нет - то возвращаемся с соответствующим сообщением. Сдедующая функция, которой необходимо передать имя новой директории, создает эту директорию командой mkdir($n_d,0777) (0777 - число, устанавливающее права доступа к созданной директории) и возвращает результат:

function create_dir($n_d){
if(mkdir($n_d,0777)){$inf="Папка ".$n_d." успешно создана";} else {$inf="Не удалось создать папку ".$n_d;}
return $inf;
}

Аналогично создается и файл:

function create_f($n_f){
if(touch($n_f)){$inf="Файл ".$n_f." успешно создан";} else {$inf="Не удалось создать файл ".$n_f;}
return $inf;
}

Теперь - функция, составляющая список содержимого переданной этой функции директории. Список формируется в виде двумерного массива, в котором элементы $fl[0][] содержат имена папок, а $fl[1][] - имена файлов. Имена оформляются в виде ссылок, для возможности дальнейших действий с папками и файлами, размеры папок определяются уже рассмотренной функцией dir_size. Функция возвращает массив имен:

function scand($dn){
if(!is_dir($dn))return;
$d = dir($dn);
while($file=$d ->read()) {
if($file==".."||$file==".") continue;
if(is_dir($dn."/".$file)){$fl[0][]= "<a href=file_manager.php?dir=".$dn."/".$file.">".$file."</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".dir_size($dn."/".$file);}
else {$fl[1][]="<a href=file_manager.php?dir=".$dn."/".$file."&fop=2>".$file."</a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;".filesize($dn."/".$file)." байт "; }
}
$d->close();
return $fl;}

Последняя функция записывает содержимое $data в файл $rp и возвращает отчет о проделанной работе:

function write_file($data,$rp){
$f = fopen($rp,"w");
if(fwrite($f,$data)){$inf="Изменения сохранены";} else {$inf="Не удалось записать файл";}
fclose($f);
return $inf;
}

Следующий блок - получение данных из форм (из будет несколько):

$dir=$_GET['dir'];
if(!$dir)$dir=$_POST['dir'];
if(!$dir)$dir=".";
$mode=$_GET['mode'];
$btnd=$_GET['btnd'];
$btnf=$_GET['btnf'];
$btnu=$_POST['btnu'];
$namedir=$_GET['namedir'];
$namef=$_GET['namef'];
$fop=$_GET['fop'];
$btn=$_POST['btn'];
$fc=$_POST['fc'];
$deld=$_GET['deld'];
$del_file=$_GET['del_file'];
$del_f=$_GET['btndel'];
$del_d=$_GET['del_dir'];
$edit=$_GET['edit'];

Здесь: $dir - текущий адрес, если не удалось получить его методом GET и он пуст, то получаем его методом POST, а если и здесь облом, то устанавливаем его на коренной каталог домена. Дальше - $mode - выбор пункта горизонтального меню, $btnd, $btnf и $btnu - переменные, определяющие в какой из форм (создания директории, создания файла или выгрузки файла) нажата кнопка, для $btnu требуется POST, потому, что в другом методу не работает форма загрузки. $namedir и $namef - имена создаваемой директории или файла. Переменная $fop определяет операцию с файлом, $btn - кнопки в форме для редактирования файла, $fc - содержимое окна редактирования. Для двух последних используется метод POST, так как методом GET нельзя передать более одного килобайта, а объемы редактируемых файлов бывают и больше. И, наконец, последними в данном блоке идут переменные для удаления директорий и файлов и переменная редактирования. После этого - обработка нажатия кнопок: если в форме редактирования нажата кнопка 'Сохранить', то записываем файл, обращаясь к соответствующей функции, остальные три строки работают точно так же:

if($btn=="Сохранить"){$info=write_file($fc,$dir);}
if($btnd)$info=create_dir($dir."/".$namedir);
if($btnf)$info=create_f($dir."/".$namef);
if($btnu)$info=upl_file($dir,$_FILES['file']['name'],$_FILES['file']['tmp_name']);

Если выбрано редактирование файла, то считываем его содержимое, маскируем специальные символы (чтобы обозреватель не принял их за настоящие), создаем форму для редактирования и выводим ее:

if($edit==1){$fc=htmlspecialchars(file_get_contents($dir));
$frme="<center><b>Редактирование файла:</b>".$dir."<BR><form name=frm action=file_manager.php method=POST><textarea name=fc rows=24 cols=64 >".$fc."</textarea><BR>
<input type=hidden name=dir value=".$dir."><input type=hidden name=fop value=2><center><input type=submit name=btn value='Сохранить'><input type=submit name=btn value='Закрыть'></center></form></center>";}

Далее - если не выбраны действия с файлами, то сканируем директорию:

if(!$fop){$m=scand($dir);}

Создаем формы подтверждения удаления директорий и файлов:

$delfile="<form action=file_manager.php ><BR><font color=#ff0000>Файл ".$dir." будет удален! </font><BR><input type=hidden name=dir value=".$dir."><input type=submit name=btndel value='Продолжить'><BR><input type=submit name=btndel value='Выход'>";

$deldir="<form action=file_manager.php ><BR><font color=#ff0000>Папка ".$dir." будет удалена! </font><BR><input type=hidden name=dir value=".$dir."><input type=submit name=del_dir value='Продолжить'><BR><input type=submit name=del_dir value='Выход'>";

Формы для загрузки файла, создания папки и файла:

$upl="<form method=POST enctype=multipart/form-data>
<input type=file name=file ><BR>
<input type=submit name=btnu value=Загрузить>
</form>";

$cdr="<form >Имя папки: <BR><input type=text name=namedir ><BR><BR><input type=hidden name=dir value=".$dir."><input type=submit name=btnd value='Создать'>";

$cdf="<form >Имя файлa: <BR><input type=hidden name=dir value=".$dir."><input type=text name=namef ><br><br><input type=submit name=btnf value='Создать'>";

Горизонтальное меню для загрузки и создания файлов и директорий:

$hmenu="<BR><a href=file_manager.php?mode=1&dir=".$dir.">Загрузить файл</a>&nbsp;&nbsp;<a href=file_manager.php?mode=2&dir=".$dir.">Создать папку</a>&nbsp;&nbsp;<a href=file_manager.php?mode=3&dir=".$dir.">Создать файл</a><BR>";

и меню для работы с файлами:

$fmenu="<BR><a href=file_manager.php?edit=1&dir=".$dir.">Редактировать</a>&nbsp;&nbsp;<a href=file_manager.php?edit=2&dir=".$dir.">Удалить</a>";

Оформляем формы для удобства вывода в массив:

$frm[1]=$upl;
$frm[2]=$cdr;
$frm[3]=$cdf;

Формируем ссалку для кнопки 'Назад', отрезая от текущего адреса все, что после последней косой черты:

if($dir=="."){$bk="";}else{$bk="Назад";}
$back=substr($dir,0,strrpos($dir,"/"));

Выводим заголовок, основное меню, сообщение о результатах работы, если такое есть и кнопку 'Назад':

echo "<h3>Диспетчер файлов</h3>".$hmenu.$info."<BR><a href=file_manager.php?dir=".$back.">".$bk."</a><BR>Путь : ".$dir."<BR>";

Если в переменной $mode что-то есть, выводим соответствующую форму:

if($mode){echo $frm[$mode];}

Далее - аналогично:

elseif($fop){echo "Файл : ".$dir." ".$fmenu;}
elseif($edit==1)echo $frme;
elseif($edit==2)echo $delfile;
elseif($deld)echo $deldir;
elseif($mode==1)echo $upl;

И, наконец, если ничего нет, то - содержимое директории:

else {
out("<b>Папка</b> ",$m[0]);
out("<i>Файл</i> ",$m[1]);}

Скачиваем, проверяем работу. Для практического использования диспетчер надо защитить паролем, ну, чтобы посторонние без разрещения ручонками шаловливыми не лазали. И оформить, чтобы глаз радовал. Как это сделать - уже знаете. Поехали вперед.

Рейтинг@Mail.ru