Урок 9. Файлы и папки в PHP. Пишем файловый менеджер.
Введение
Рано или поздно каждому новичку придется столкнуться с проблемой создания приложения, функционал которого должен позволять просматривать папки и файлы на сервере. Т.е необходимо реализовать файловый менеджер. Применяется данное приложение в административных модулях и на хостингах, для управления файлами через веб-браузер. Конечно в сети есть множество навороченных скриптов, с применением AJAX или javascript’а, функциональность которых практически ничем не отличается от десктопных, но цель нашего урока – ознакомиться с элементарными функциями для работы с папками и файлами.
Детали
Рассмотрим основные функции, с которыми мы сегодня ознакомимся:
- Чтение и вывод содержимого директории;
- Создание папки;
- Удаление папки и файлов;
- Переименование папок и файлов;
- Получение размера файлов.
Самая простая задача, которая сейчас стоит перед нами – это научиться считывать содержимое директории на сервере, группировать данные(файла, папки) и выводить их в браузер. Данные скрипты можно тестировать и на локальном сервере, для этого создайте в папке www папку dir, в ней будут наши скрипты. В папке dir создайте папку data. Папка data будет нашей рабочей директорией, в ней необходимо создать несколько любых папок и накидать файлы разных форматов для тестирования.А теперь приступим к программированию. Наш файловый менеджер будет состоять из нескольких файлов:
- index.php – главная страница, с основными логическими операциями;
- functions.inc.php – файл будет содержать все необходимые функции для работы;
- config.inc.php – файл конфигурации.
Чтение директории
Чтобы в дальнейшем небыло вопросов я приведу небольшой фрагмент кода, в котором происходит сканирование директории и вывод содержимого в браузер.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //Указываем рабочую папку по умолчанию $url = "data"; //Проверяем, является ли директорией if (is_dir($url)) { //Проверяем, была ли открыта директория if ($dir = opendir($url)) { //Сканируем директорию while (false !== ($file = readdir($dir))){ //Убираем лишние элементы if ($file != "." && $file != "..") { //Выводим спиоск в браузер echo $file."<br/>"; } } //Закрываем директорию closedir($dir); } } |
Это довольно простое решение, честно признаюсь что данный пример я взял из документации, т.к. ничего другого тут не придумаешь. Это основной принцип, от которого мы будем отталкиваться.
functions.inc.php
Создаем файл functions.inc.php и помещаем туда следующий список функций:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //Листинг папок function listing ($url,$mode) { //Проверяем, является ли директорией if (is_dir($url)) { //Проверяем, была ли открыта директория if ($dir = opendir($url)) { //Сканируем директорию while (false !== ($file = readdir($dir))) { //Убираем лишние элементы if ($file != "." && $file != "..") { //Если папка, то записываем в массив $folders if(is_dir($url."/".$file)) { $folders[] = $file; } //Если файл, то пишем в массив $files else {$files[] = $file;} } } } //Закрываем директорию closedir($dir); } //Если режим =1 то возвращаем массив с папками if($mode == 1) {return $folders;} //Если режим =0 то возвращаем массив с файлами if($mode == 0) {return $files;} } |
У данной функции в качестве аргументов передаются путь и режим. Если $mode = 1,то функция возвращает массив с папками, если 0, то массив с файлами. Продолжим.
1 2 3 4 5 6 7 | //Функция создания папки function makedir ($url){ //Вырезаем пробелы и хтмл-тэги $url = trim(htmlspecialchars($url)); //Если папка создается возвращаем TRUE if(@mkdir($url)){return TRUE;} else{return FALSE;} } |
Данная функция будет создавать папку. Как он будет работать? Для этого существует замечательная функция – mkdir(). Все остальное дело прямых рук=)
1 2 3 4 5 6 7 8 9 | //Функция переименования function frename ($url,$oldname,$nname){ $nname = trim(htmlspecialchars($nname)); $oldname = trim(htmlspecialchars($oldname)); $url = trim(htmlspecialchars($url)); if(@rename($url."/".$oldname,$url."/".$nname)) {return TRUE; } else {return FALSE; } } |
Достаточно простая функция, аргументами которой являются путь, имя старого файла/папки и имя нового файла/папки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | function removedir ($directory) { $dir = opendir($directory); while(($file = readdir($dir))) { if ( is_file ($directory."/".$file)) { unlink ($directory."/".$file); } else if ( is_dir ($directory."/".$file) && ($file != ".") && ($file != "..")) { removedir ($directory."/".$file); } } closedir ($dir); rmdir ($directory); return TRUE; } |
Хорошая функция, которая удаляет все вложенные файлы и папки. В качестве аргумента передаем путь(имя) до папки.
1 2 3 | function removefile ($path) { if(unlink($path)) { return TRUE; } else { return FALSE; } } |
Наиболее упрощенная функция, которая удаляет файл.В качестве аргумента передаем путь(имя) до файла.
1 2 3 4 5 | function updir( $path ){ $last = strrchr( $path, "/" ); $n1 = strlen( $last ); $n2 = strlen( $path ); return substr( $path, 0, $n2-$n1 ); } |
А вот это очень полезная функция, которая позволит получать имя предыдущей папки.
1 2 3 4 5 | //Получаем размер файла function fsize($path) { return substr(filesize($path)/1024, 0, 4); } ?> |
Простейшая функция для получения размера файла. В качестве аргумента передаем путь до файла. Сохраняем файл с функциями и переходим к главному исполнительному файлу.
index.php
Листинг файлов и папок
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <?php //Подключаем файл конфигурации include("config.inc.php"); //Подключаем файл с функциями include("functions.inc.php"); //Указываем рабочую папку по умолчанию if($_GET['url']) {$url = $_GET['url']; } //Шапка echo 'Текущая директория: '.$url.'<br/>'; echo '<a href=".">[корень]</a> '; echo '<a href="index.php?url='.updir($url).'">[вверх]</a> '; echo '<a href="index.php?mkdir=1&url='.$url.'">[создать папку]</a><br/><br/>'; //Листинг папок if(listing($url,1)) { foreach(listing($url,1) as $f) { echo '<a href="index.php?rename=1&url='.$url.'&fname='.$f.'">[переименовать]</a>'; echo '<a href="index.php?rmdir=1&url='.$url.'&fname='.$f.'">[удалить]</a> '; echo '<img src="img/dir.gif" alt=""/><a href="index.php?url='.$url."/".$f.'">'.$f.'</a><br/>'; }} //Листинг файлов if(listing($url,0)) { foreach(listing($url,0) as $f) { echo '<a href="index.php?rename=1&url='.$url.'&fname='.$f.'">[переименовать]</a>'; echo '<a href="index.php?rmfile=1&url='.$url.'&fname='.$f.'">[удалить]</a> '; echo '<img src="img/'.strtolower(substr($f,-3)).'.gif" alt=""/>'.$f.' - '.fsize($url).'<br/>'; }} |
Этот фрагмент можно условно поделить на 3 части:
- Первая это «шапка» – меню, которое статично и отображается во всех разделах одинаково. Сама «шапка» содержит 3 ссылки: корень, вверх и новая папка.
- Листинг папок. Здесь все просто, при помощи функции foreach производим вывод данных из массива. Рядом с каждой папкой имеются ссылки: переименовать и удалить.
- Листинг файлов. Здесь тоже просходит вывод из массива $files, поэтому рядом с каждым файлом имеются ссылки: переименовать и удалить. Также рядом с каждым файлом выводиться его размер.
Чтобы было нагляднее, я сделал отображение иконки соответсвующей типу файла.
Отдельное слово про навигацию. Здесь все достаточно просто, если скрипту не передаются никакие параметры, то папка по умолчанию будет data, если же мы перешли в другую папку, то $url = $_GET['url'], т.е. тот путь который мы передали по ссылке.
Для того чтобы осуществить подьем на уровень выше («вверх») мы используем функцию updir(). Я думаю вы самостоятельно её разберете, в ней нет ничего сложного.
Создание папок
Следующий скрипт позволяет добавлять папки.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | //Создание папок if($_GET['mkdir']) { if(!$_POST['add']) { echo '<br/><form name="" action="?mkdir=1" method="post">'; echo 'Имя новой папки:<br/>'; echo '<input name="ndir" type="text" value="" maxleight="25">'; echo '<input name="url" type="hidden" value="'.$_GET['url'].'"><br/>'; echo '<input type="submit" name="add" value="создать"></form>'; } else { if(makedir($_POST['url']."/".$_POST['ndir'])!== FALSE) { header("location:index.php?url=".$_POST['url']); } else {echo 'Ошибка <br/>';} }} |
Для того чтобы он заработал, скрипту index.php необходимо передать переменную $_GET['mkdir'] . Данное действие реализовано ссылкой в шапке. Обязательно по ссылке передаем текущую рабочую директорию в переменной $url. После того как мы нажали на ссылку, снизу будет отображена форма, в которой необходимо ввести имя новой папки. После нажатия кнопки сработает функция makedir().
Ну вот вроде и разобрались с функцией создания папки, продолжим дальше.
Удаление папок
Чтобы удалить папку нам необходимо использовать следующий код:
1 2 3 4 5 | //Удаление папок if($_GET['rmdir']){ if(removedir($_GET['url']."/".$_GET['fname']) !== FALSE) { header("location:index.php?url=".$_GET['url']); } } |
Для того чтобы это условие выпонилось, необходимо файлу index.php передать нужные параметры, т.к. при листинге файлов и папок выводятся сервисные ссылки, которые содержат необходимые параметры, то реализовать это будет несложно. Здесь $rmdir=1 означает то, что будет выполнено условие на удаление – if($_GET['rmdir']){} , а необходимые параметры передаем функции removedir() через GET параметры , при успешной завершений которой, происходит редирект на последнюю рабочую папку.
Удаление файлов
Идентичный скрипт, который отличается только исполняемой функцией.
1 2 3 4 | //Удаление файлов if($_GET['rmfile']){ if(removefile($_GET['url']."/".$_GET['fname']) !== FALSE) { header("location:index.php?url=".$_GET['url']); |
Работа этого скрипта полностью повторяет принцип удаления папки.
Переименование папок и файлов
Чтобы переименовать файл, нам необходимо знать путь до него, его старое имя и естественно новое имя. Следующий фрагмент кода позволяет переименовывать файлы и папки. Не забывайте что при листинге напротив каждого файла и папки есть ссылка, которая содержит необходимые параметры (путь,имя файла).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | //Переименование папок и файлов if($_GET['rename']) { if(!$_POST['rename']) { echo '<br/><form name="" action="?rename=1" method="post">'; echo 'Новое имя:<br/>'; echo '<input name="nname" type="text" value="'.$_GET['fname'].'" maxleight="25">'; echo '<input name="url" type="hidden" value="'.$_GET['url'].'"><br/>'; echo '<input name="oldname" type="hidden" value="'.$_GET['fname'].'">'; echo '<input type="submit" name="rename" value="ok"></form>'; } else { if(frename($_POST['url'],$_POST['oldname'],$_POST['nname'])!== FALSE) { header("location:index.php?url=".$_POST['url']); } else {echo 'Ошибка <br/>';} } } ?> |
Здесь сначала отображается форма, которая дает пользователю сменить имя, после ввода необходимых данных и нажатия на кнопку, запускается функция frename(). Если все завершилось без проблем, то происходит редирект на последнюю папку, в которой мы находились.
config.inc.php
Небольшой файл конфигурации.
1 2 3 4 5 | <?php //Папка по умолчанию $url="data"; ?> |
Исходники
Заключение
Конечно данный скрипт не претендует на то чтобы Вы его использовали в своих проектах, т.к. здесь достаточно много различных уязвимостей, но он вполне подходит для поверхностного изучения необходимых функций. Если вам не терпиться можете запросто эксперементировать и добавлять необходимый функционал. Хочу сказать что в следующих уроках мы добавим несколько ключевых функций (копирование, перемещение, загрузка файла на сервер и др), поработаем над дизайном и защитой.
Подпишись на RSS, впереди много интересного.

Август 8th, 2008 at 00:56
Хорошо
Да нет, не составит особого труда под загруз переделать
Я просто делаю для wap. Этого достаточно
Август 7th, 2008 at 22:57
2 Станислав
Достаточно много чего необходимо переделать =).Сама по себе постраничная навигация не так сложна. Просто выводим массив с данными не целиком, а фрагментами. Как это сделать напишу позже=) Возможно завтра
Август 7th, 2008 at 20:50
Я придумал назначение этому скрипту, его чуть-чуть подредактировать и выйдет отличный загруз-центр. Но я не знаю, как сделать постраничный вывод файлов и папок. Можете помоч?
Август 4th, 2008 at 15:06
ок, спасибо. Я разобрался
Август 4th, 2008 at 09:27
2 Станислав
Это достаточно просто сделать. Просто для начала сортируем массив в обратном порядке:
2
3
4
5
6
7
closedir($dir);
}
//Сортируем в обратном порядке
rsort($files);
//Содержимое массива
print_r($files);
А потом при помощи foreach() выводим данные.
Август 4th, 2008 at 01:20
Хороший мануал. Вот только можно вопрос? А как в первом коде, по выводу списка файлов из директории, сделать сортировку вывода названий файлов в порядке убывания? В папке хранятся файлы с примерно такими именами 413151664.dat и тд. Спасибо
Август 1st, 2008 at 14:48
2 Андрей Дмитриевич
Чуть позже напишу, сейчас совсем не хватает времени.
Август 1st, 2008 at 14:42
Отличная статья! хорошо бы еще защиту.
Июль 31st, 2008 at 16:01
[...] для файлового менеджера из предыдущего урока “Файловый менеджер на PHP“. Для того чтобы добавить возможность загрузки [...]
Июль 30th, 2008 at 23:49
Хорошие материалы, молодец!
Ты предлагал обмен ссылками – занес твою ленту в свой агрегатор, ну и, конечно, поставил ссылку в блоге.