Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

PHP5_nachinayushim

.pdf
Скачиваний:
29
Добавлен:
20.03.2015
Размер:
26.79 Mб
Скачать

334 Глава 7

$file_info_array["fileowner"] = fileowner($file);

}else {

$file_info_array["fileatime"] = "недоступно"; $file_info_array["filegroup"] = "недоступно";

$file_info_array["fileowner"] = "недоступно";

}

$extension = array_pop(explode(".", $file));

if (in_array($extension, $text_file_array)) { $file_info_array["filetype"] = "текстовый";

} else {

$file_info_array["filetype"] = "двоичный";

}

return $file_info_array;

}

Обратите внимание, как с помощью функции explode(".", $file) из задан+ ного имени файла выделяется расширение. Функция разделяет имя файла, используя в качестве разделителя точку (.), и возвращает в виде массива полученные в резуль+ тате части имени. Последний элемент извлекается из массива с помощью функции array_pop() и сохраняется в переменной $extension. В данном случае расшире+ ние не является вторым элементом.

В последнем блоке файла common_php5_02.inc.php создается массив расшире+ ний файлов:

// задаем расширения обрабатываемых файлов

$text_file_array = array( "txt", "htm", "html", "php", "inc", "dat" );

Теперь можно создавать структуру главного файла обработки, editor_php5.php. Сначала вводится заголовок для обычной HTML+страницы:

<html>

<head><title>Текстовый редактор</title></head> <body>

<form method="POST" action="<?php echo $_SERVER['PHP_SELF']; ?>"> <input type="hidden" name="posted" value="true">

Затем начинается PHP+код и подключается (с помощью функции require()) файл common_php5.inc.php. После чего задается используемый каталог:

require("common_php5_02.inc.php"); //определение каталога по умолчанию

$dir = "./docs";

Следующий фрагмент кода проверяет, нажал ли пользователь кнопку, и если это так, то устанавливает соответствующее значение для окончательного оператора select..case:

if (isset($_POST['save_edited_file'])) { $action_chosen = "save_file";

} elseif (isset($_POST['create_new_file'])) {

$action_chosen = "save_file"; } elseif (isset($_POST['edit_existing_file])) { $action_chosen = "edit_existing_file";

}

Далее начинается оператор select..case и создается case+блок save_file. Этот код проверяет существование файла, и если файл существует, то используется JavaScript+сценарий, запрашивающий у пользователя подтверждение на перезапись данного файла:

switch ($action_chosen) { case "save_file";

Файлы и каталоги 335

if (file_exists("$dir/$_POST[filename]")) {

echo "<script>result = confirm(\"Перезаписать файл '$dir/$_POST[filename]'?\"); if(!result) history.go

(-1);</script>";

}

Для отправки пользователю сообщения об ошибке, в случае если попытка открыть (или создать) файл оказалась неудачной, используется функция error_message():

if ($file = fopen("$dir/$_POST[filename]", "w")) { fputs($file, $_POST[filebody]);

fclose($file);

}else {

error_message("Невозможно сохранить файл $dir/$_POST[filename].");

}

Последний фрагмент кода в case+блоке save_file использует HTML для отобра+ жения простых кнопок, позволяющих пользователю выполнять доступные в прило+ жении операции. Обратите внимание на отличие кода создания листинга каталогов для наполнения выпадающего списка. Тот же код используется в case+блоке по умол+ чанию. В конце этого блока необходимо поместить ключевое слово break:

//отображение основных кнопок

?>

<table border="1" align="center"><tr><td>

<strong>Создать (или перезаписать) новый файл или редактировать существующий файл</strong>

</td></tr>

<tr><td>

<input type="submit" name="create_new_file" value="Создать новый файл"> <input type="text" name="filename" value="new.txt">

</td></tr>

<tr><td>

<input type="submit" name="edit_existing_file" value="Редактировать существующий файл">

<select name="existing_file"> <?php

if($dp = opendir($dir)) { while($file = readdir($dp)) {

if($file !== '.' && $file !== '..' && is_file($dir."/".$file)) {

?>

<option value="<?php echo $file; ?>"> <?php echo $file; ?></option>

<?php

}

}

} else {

error_msg("Невозможно открыть каталог $dir.");

}

closedir($dp);

?>

</select>

</td></tr></table>

<?php

break;

336 Глава 7

Рассмотрим case+блок edit_existing_file. Сценарий устанавливает свойства файла, включая filebody, и помещает результаты работы функции file_info() в мас+ сив $file_info_array:

case "edit_existing_file";

$filepath = "$dir/$_POST[existing_file]"; $filebody = implode("",file($filepath)); $file_info_array = file_info("$filepath");

Затем необходимо проверить, является ли данный файл текстовым, и если это не так, то записать в свойство filebody уведомление о том, что данный файл редакти+ рованию не подлежит:

if ($file_info_array["filetype"] != "text") {

$filebody = $filepath . " не является текстовым файлом. Редактирование невозможно.";

$editable = 0; } else {

$editable = 1;

}

Отображение информации о файле:

?>

<table border="1" width="70%" align="center">

<tr><th width="100%" colspan="2"> <center><strong>Информация о существующем файле <?php echo

"$dir/$_POST[existing_file]"; ?> </td></tr>

<?php

$file_info_array = file_info("$dir/$_POST[existing_file]");

foreach ($file_info_array as $key=>$val) {

echo "<tr><th width=\"30%\">". ucfirst($key)

. "</td><td width=\"70%\">" . $val

. "</td></tr>\n";

}

?>

</table>

Последние строки case+блока edit_existing_file позволяют пользователю от+ редактировать и сохранить файл:

<br>

<table border="1" align="center"><tr><td> <strong>Редактирование существующего файла <?php echo

$_POST['existing_file']; ?></strong> </td></tr>

<tr><td>

<?php

if ($editable == 0) { echo $filebody;

} else { ?>

<input type="hidden" name="filename" value="<?php echo $_POST['existing_file]; ?>">

<textarea rows="4" name="filebody" cols="40" wrap="soft"> <?php

echo "$filebody"; ?>

</textarea><br>

<input type="submit" name="save_edited_file" value="Сохранить файл"> <?php

Файлы и каталоги 337

}

?>

</td></tr></table>

<?php

break;

Блок default представляет собой копию последней части case+блока save_file:

default;

//отображение основных кнопок

?>

<table border="1" align="center"><tr><td>

<strong>Создать (или перезаписать) новый файл или отредактировать существующий</strong>

</td></tr>

<tr><td>

<input type="submit" name="create_new_file" value="Создать новый файл"> <input type="text" name="filename" value="new.txt">

</td></tr>

<tr><td>

<input type="submit" name="edit_existing_file" value="Редактировать существующий файл">

<select name="existing_file"> <?php

if($dp = opendir($dir)) { while($file = readdir($dp)) {

if($file !== '.' && $file !== '..' && is_file ($dir."/".$file)) {

?>

<option value="<?php echo $file; ?>"><?php echo $file; ?></option> <?php

}

}

} else {

error_msg("Невозможно открыть каталог $dir.");

}

closedir($dp);

?>

</select> </td></tr></table> <?php

break;

В последней части сценария закрывается оператор select..case, а также завер+ шается HTML+код для страницы, включая закрывающий тег </form>.

}

?>

</form>

</body>

</html>

Данный сценарий очень хорошо иллюстрирует использование функций для рабо+ ты с файловой системой.

Загрузка файлов на сервер

Созданный только что ‘‘навигатор’’ можно улучшить, добавив в него возмож+ ность загружать файлы с локальной машины на сервер. PHP предоставляет простой способ для внедрения в приложение подобной функциональности. Загружать файлы

338 Глава 7

с помощью браузера позволяет элемент HTML+формы <input>, имеющий тип file. Для загрузки файлов также необходимо установить в теге <form> атрибут enctype (со значением multipart/form-data), который при создании обычной формы, как правило, опускается.

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

<form method="POST" enctype="multipart/form-data"

action="<?php echo "$_SERVER[PHP_SELF]?action=upload_file&dir=$dir"; ?>">

Локальный файл <input type="file" name="userfile"> <input type="submit" name="submit" value="Загрузить">

</form>

Атрибут action данной формы должен указывать на PHP+сценарий, который бу+ дет обрабатывать загружаемый файл. Вводить второе текстовое поле необходимо только в том случае, если желательно предоставить пользователю возможность зада+ вать имя, с которым загружаемый файл будет сохраняться на сервере.

Как только файл загружается, через суперглобальный массив $_FILES становятся доступны следующие переменные:

Переменная

Описание

 

 

$_FILES[userfile]

Массив в $_FILES, содержащий другие значения

$_FILES[userfile][name]

Исходный (на пользовательской машине) путь и имя

 

загруженного файла

$_FILES[userfile][size]

Размер загруженного файла в байтах

$_FILE[userfile][type]

Тип файла (если браузер предоставляет данную

 

информацию)

Предположим, пользователь с помощью формы только что загрузил zip+файл C:\bsdocs\projects.zip размером 20 000 байт. В таком случае указанные пере+ менные содержат следующие значения:

$_FILES[userfile][tmp_name]: путь к файлу во временном каталоге (который устанавливается в php.ini) и временное имя файла в формате "php-###" (где "###" ++++++ номер, автоматически генерируемый PHP), например, "/tmp/php-512".

$_FILES[userfile][name]: "C:\bsdocs\projects.zip". $_FILES[userfile][size]: 20000.

$_FILES[userfile][type]: "application/x-zip-compressed".

Эти значения при желании можно записать в обычные переменные, например, так:

//определение параметров пользовательского файла $userfile_name = $_FILES['userfile']['name']; $userfile_tmp_name = $_FILES['userfile']['tmp_name']; $userfile_size = $_FILES['userfile']['size']; $userfile_type = $_FILES['userfile']['type']; if(isset($_ENV['WINDIR'])) {

$userfile = str_replace("\\\\","\\", $_FILES['userfile']['name']);

}

Загружаемый файл сохраняется во временном каталоге, заданном в файле php.ini, и уничтожается по окончании данного запроса, поэтому его необходимо скопировать в какой+либо другой каталог. По соображениям безопасности для этого рекомендуется использовать функцию move_uploaded_file() вместо copy():

Файлы и каталоги 339

$archive_dir = "./docs";

$filename = basename($userfile_name);

if(!@move_uploaded_file($userfile, "$archive_dir/$filename")) echo "Ошибка: невозможно скопировать файл $filename.";

else echo "Файл $filename успешно загружен.";

Можно установить ограничение на размер загружаемых файлов и с помощью пе+ ременной $userfile_size проверять, не превышает ли размер загружаемого файла заданное ограничение:

$archive_dir = "./docs"; $max_filesize = 200000;

$filename = basename($userfile_name);

if($userfile_size > $max_filesize)

echo "Ошибка: файл $filename слишком велик. " .

. "Максимальный размер загружаемого файла: " . number_format($max_filesize) . " байтов.";

else if(!copy($userfile, "$archive_dir/$filename"))

echo "Ошибка: невозможно скопировать файл $filename."; else echo "Файл $filename успешно загружен.";

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

<input type="hidden" name="max_file_size" value="200000">

...

if($userfile_size > $max_file_size)

echo "Ошибка: файл $filename слишком велик. " .

. "Максимальный размер загружаемого файла: " . number_format($max_filesize) . " байт.";

Установка данного ограничения внутри сценария ++++++ гораздо более безопасный ме+ тод, потому что злоумышленник может отредактировать содержимое Web+страницы, содержащей форму для загрузки, и установить любое ограничение.

Практика Загрузка файлов

Ниже приведен завершенный пример реализации функции загрузки файлов:

<?php //file_upload.php

function upload_form() { ?>

<table border="1" align="center"> <tr><td>

<form method="POST" enctype="multipart/form-data"

action="<? echo $_SERVER['PHP_SELF'] ?>">

Выберите файл для загрузки

<input type="file" name="userfile">

<input type="submit" name="action" value="Загрузить"> </form>

</td></tr>

</table>

<?

}

function upload_file() { //установка архивного каталога

$archive_dir = "./docs";

//определение параметров пользовательского файла $userfile_name = $_FILES['userfile']['name']; $userfile_tmp_name = $_FILES['userfile']['tmp_name']; $userfile_size = $_FILES['userfile']['size']; $userfile_type = $_FILES['userfile']['type'];

340 Глава 7

if(isset($_ENV['WINDIR'])) {

$userfile = str_replace("\\\\","\\", $_FILES['userfile']['name']);

}

$filename = basename($userfile_name); if($userfile_size <= 0) die ("Файл $filename пуст.");

if(!@move_uploaded_file($userfile_tmp_name, "$archive_dir/$filename")) die("Невозможно скопировать файл $userfile_name в $filename.");

if(isset($_ENV['WINDIR']) && !@unlink($userfile)) die ("Невозможно удалить файл $userfile_name.");

echo "Файл $filename был успешно загружен.<BR>";

echo "Размер файла: " . number_format($userfile_size) . "<BR>"; echo "Тип файла: $userfile_type<BR>";

}

?>

<html>

<head><title>Загрузка файла</title></head> <body>

<?php

if($_POST[action] == 'Загрузить') { upload_file();

} else { upload_form();

}

?>

</body>

</html>

На рис. 7.11 изображена форма для загрузки (в данном случае для загрузки выбран файл 2.gif).

Рис. 7.11.

Файлы и каталоги 341

Пользователь, загружающий данный файл, в случае успешной загрузки увидит страницу, показанную на рис. 7.12.

Рис. 7.12.

Как это работает

Когда пользователь загружает файл со своей локальной машины, сценарий снача+ ла получает значения массива $_FILES, а затем определяет платформу, на которой работает. Если таковой является Windows, то все вхождения двойной обратной косой черты необходимо заменить на одинарную обратную косую черту:

//установка архивного каталога

$archive_dir = ./docs";

//определение параметров пользовательского файла $userfile_name = $_FILES['userfile']['name']; $userfile_tmp_name = $_FILES['userfile']['tmp_name']; $userfile_size = $_FILES['userfile']['size']; $userfile_type = $_FILES['userfile']['type']; if(isset($_ENV['WINDIR'])) {

$userfile = str_replace("\\\\","\\", $_FILES['userfile']['name']);

Если размер файла меньше нуля, то пользователь отправил форму, не указав за+ гружаемый файл:

if($userfile_size <= 0) die ("Файл $filename пуст.");

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

342 Глава 7

Резюме

В настоящей главе рассматривались функции для работы с файлами, в том числе функции для чтения и записи файлов. На примерах было продемонстрировано созда+ ние простого текстового редактора на Web+странице, а также работа с каталогами и создание сценария для обхода дерева каталогов.

Данная глава охватывает большинство основных PHP+функций для работы с фай+ лами и каталогами. В некоторых из них используется дескриптор файла или катало+ га ++++++ указатель, ссылающийся на открытый файл или каталог. Работа с такими функ+ циями состоит из следующих этапов:

1.Открытие файла или каталога с помощью функции fopen() или opendir().

2.Работа с открытым файлом или каталогом с помощью функций fread(), fgets(), fpassthru() и readdir() др.

3.Закрытие файла или каталога с помощью функций fclose() или closedir().

Наконец, в главе рассматривалось создание текстового редактора, который может сканировать дерево каталогов и манипулировать записями в нем.

В главе не обсуждались некоторые редко применяемые в Web+приложениях функ+ ции. Полный перечень функций для работы с файлами и каталогами можно просмот+ реть на Web+сайте PHP http://php.net/manual/ref.filesystem.php.

Упражнение

Создайте PHP+приложение, которое можно использовать для поиска определен+ ного каталога в правильно заданном родительском каталоге. Приложение должно просматривать указанный каталог, а также все каталоги, которые в нем находятся.

8

XML

XML (eXtensible Markup Language ++++++ расширяемый язык разметки) ++++++ сравнитель+ но новая идея. Первоначально XML разрабатывался как удобный для человека способ обмена структурированными данными, но впоследствии весьма быстро получил ши+ рокое распространение также как средство хранения структурированной информа+ ции. Хотя XML во многом отличается от баз данных, он, как и базы данных, представ+ ляет собой метод форматирования и/или постоянного хранения данных, а также имеет свои преимущества и недостатки.

XML на самом деле является не языком, а спецификацией для создания собствен+ ных языков разметки. XML представляет собой подмножество языка SGML (Standard Generalized Markup Language ++++++ стандартный обобщенный язык разметки, предшест+ венник HTML). XML предназначен для упрощения обмена данными между несовмес+ тимыми приложениями. Форматирование XML+документов очень похоже на форма+ тирование HTML+документов. В отличие от HTML, который имеет фиксированное множество дескрипторов и атрибутов, определенных в спецификации HTML, XML позволяет писать собственные дескрипторы (которые также называются элементами) и атрибуты и, таким образом, предоставляет возможность определения собственного языка в XML+ или любом другом определении. В сущности, с помощью XML можно форматировать любые данные.

В дополнение к этому XML предоставляет средства для создания определений данных, которые будут доступны другим приложениям в сети. Таким образом, два приложения, которые ничего ‘‘не знают’’ друг о друге, но оба способны анализиро+ вать XML+документы, смогут обмениваться данными друг с другом.

По этим причинам XML быстро становится стандартом обмена данными, а в PHP5 имеется множество новых средств и функций, которые ускоряют работу с XML+ данными и делают ее эффективнее и понятнее. В PHP5 включены все XML+функции PHP4, а также новые функции, основанные на simpleXML (встроенное PHP+ расширение, поддерживающее общие XML+операции).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]