http://sulfurzona.com/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Forum
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 

PHP и WEB для новичков (часть 11):

 
 

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

 
PHP и WEB для новичков
Итак, с формами мы закончили, хотя остаётся ещё один тип данных, который можно передавать через форму - это загружаемые файлы. Думаю что все, кто в интернете видел галереи изображений или пользовался веб-почтой, сталкивался с формами для загрузки файлов на сервер, например, такими (рис. 1):
 
<html>
<body>
<form enctype="multipart/form-data" action="test_upload.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="60000" />
файл: <input name="userfile" type="file" />
<input type="submit" value="Загрузить" />
</form>
</body>
</html>
 
Рис. 1
 
Параметр формы enctype="multipart/form-data" указывает на то, что в этой форме могут быть поля для передачи файлов. В action, разумеется, указывается скрипт, обрабатывающий данные этой формы после отправки, и методом формы обязательно указываем post.
 
Первое поле формы - MAX_FILE_SIZE определяет максимальный размер загружаемого файла в байтах. Это поле необходимо лишь для браузера. Мне не встречались браузеры, которые бы реагировали на это поле, но всё же его рекомендуют указывать.
PHP имеет своё ограничение на размер файла, которое указывается в конфигурации PHP. Файлы, превышающие этот размер, просто не загружаются. Следует отметить, что если форма содержит поля, помеченные как hidden (скрытый), то при передаче формы, данные из скрытых полей тоже передаются в обрабатывающий скрипт.
 
Аналогично параметрам, находящимся в массивах $_GET или $_POST, информация о загруженных файлах хранится в массиве $_FILES. Сами загруженные файлы находятся во временной папке сервера (для Денвера, например, в c:/temp) до тех пор, пока их не переместят в нужную папку вызовом функции move_uploaded_file(), формат вызова которой:
 
move_uploaded_file ( string filename, string destination )
 
Следующий пример иллюстрирует загрузку файла в папку веб-сервера:
 
<html>
<head><title>Загрузка файла</title></head>
<body>
<form enctype="multipart/form-data" action="test_upload.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="2000000" />
файл: <input name="userfile" type="file" />
<input type="submit" value="Загрузить" />
</form>
<?
if(count($_FILES)){
$upload_name = $_SERVER["DOCUMENT_ROOT"]."/".
basename($_FILES['userfile']['name']);
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $upload_name))
echo "Файл успешно загружен в папку ".dirname($upload_name)."n";
else echo "Ошибка загрузки файла.n";
}
?>
</body>
</html>
 
После вывода формы для загрузки выполняется проверка массива $_FILES. Если его размер ненулевой, то это означает, что был загружен файл. В этом случае сначала формируем имя и путь назначения загружаемого файла в переменной $upload_name.
Путь к файлу - $_SERVER["DOCUMENT_ROOT"] - это глобальная переменная, содержащая корневую папку веб-сервера (в нашем случае - z:/home/multimedia/www). Имя файла хранится в элементе массива $_FILES['userfile']['name'], а имя файла во временной папке хранится в элементе $_FILES['userfile']['tmp_name'].
 
Выполняя move_uploaded_file() мы перемещаем файл из временной папки в папку $_SERVER["DOCUMENT_ROOT"]. В случае успешной загрузки файл будет перемещён и функция move_uploaded_file() возвратит true и скрипт выдаст сообщение, что файл был успешно загружен в папку (функция dirname() возвращает путь к файлу, например, z:homemultimediawww для файла z:homemultimediawwwimg.jpg). Иначе возвратит false и выдаст сообщение об ошибке.
Команда basename ранее уже встречалась нам, но я рассказывал о ней вскользь. Она возвращает имя файла из указанного пути:
 
basename ( путь [, суффикс] )
 
Если имя файла оканчивается на суффикс, он также будет отброшен. Пример:
 
<?
$path = "/home/multimedia/www/index.php";
echo "<BR>".basename($path);
echo "<BR>".basename($path, ".php");
?>
 
выдаст:
 
index.php
index
 
Ну да вернёмся к скрипту загрузки файлов. Рекомендую поэкспериментировать с этим скриптом загрузки, но помните, что по умолчанию максимальный размер загружаемого файла в Денвере - 2 Мб.
Далее напишем небольшой скрипт, который будет загружать на сервер только MP3-файлы и заполнять БД информацией о них. Сперва, в папке сайта создадим папку "mp3", куда будем загружать файлы.
 
Затем следует увеличить максимальный размер загрузки, поскольку большинство MP3-файлов могут превышать существующее ограничение. Это делается так: в файле z:/usr/local/php/php.ini находим строку upload_max_filesize = 2M и заменяем 2M, например, на 8M.
 
Если необходимо загружать файлы ещё большего размера, то в этом же файле php.ini следует отыскать и исправить строку post_max_size = 8M, где post_max_size должен быть не меньше upload_max_filesize. После этого перезапускаем Денвер.
Следующий скрипт назовём upload_mp3.php:
 
<?
if( count($_POST) ) {
// Считываем поля из массива $_POST
$title = $_POST['title'];
$bitrate = $_POST['bitrate'];
$year = $_POST['year'];
} else { $title="";$bitrate="";$year=""; }
?><html>
<head><title>Загрузка MP3</title></head>
<body>
Добавить файл в архив
<form enctype="multipart/form-data" action="upload_mp3.php" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="8000000" />
<table>
<tr><td align="right">Файл:</td>
<td><input name="userfile" type="file" /></td></tr>
<tr><td align="right">Название</td>
<td><input type="text" name="title" value="<?=$title?>" /></td></tr>
<tr><td align="right">Битрейт</td>
<td><input type="text" name="bitrate" value="<?=$bitrate?>" /></td></tr>
<tr><td align="right">Год</td>
<td><input type="text" name="year" value="<?=$year?>" /></td></tr>
</table>
<input type="submit" value="Добавить" />
</form>
<?
// Проверяем, правильно ли заданы все необходимые поля
if( count($_POST) && ($title == "" ¦¦ $bitrate == "" ¦¦ $year == "") ){
echo "Необходимо заполнить все поля.<br />n";
echo "</body>n</html>";
exit;
}
// Подключаемся к БД
$link = @mysql_connect("localhost", "multimedia_user", "12345");
if(!$link){
echo "невозможно подключиться к серверу: ".mysql_error();
echo "</body>n</html>";
exit;
}
if(!mysql_select_db("multimedia")){
echo "невозможно подключиться к БД: ".mysql_error();
echo "</body>n</html>";
exit;
}
if(count($_FILES)){
// Загружаем файл
$filename = basename($_FILES['userfile']['name']);
$upload_name = $_SERVER["DOCUMENT_ROOT"]."/mp3/$filename";
if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_name)) {
echo "Файл "$filename" успешно загружен. n";
// Добавляем информацию о файле в БД
$filesize = filesize($upload_name);
mysql_query("INSERT INTO mp3(filename, title, filesize, bitrate, year)".
"VALUES('$filename', '$title', $filesize, $bitrate, $year)");
}
else echo "Ошибка загрузки файла.n";
}
?>
</body>
</html>
 
Предлагаю разобраться с работой данного скрипта самостоятельно, поскольку большая часть кода вам уже должна быть знакома, а ключевые детали помечены комментариями. Я лишь поясню некоторые моменты, которые могут быть непонятными.
Во-первых, конструкция вида <?=$title?> используется для краткой записи вывода значения переменной в HTML-коде. Вместо этого можно было бы написать <? echo $title; ?>
Во-вторых, неизвестная ещё нам функция filesize() принимает полный путь к файлу с его именем и возвращает его размер в байтах. Поэтому не имеет смысла задавать размер файла в форме.
 

Режим доступа к файлу

 
Бывают случаи, когда необходимо назначить разрешающие права (permissions) для доступа к файлу (таблица 1).
 
Таблица 1. Разрешающие права доступа к файлу
Маска
Пользователь
Доступные действия
400
Владелец (Owner)
Чтение (Read)
200
Владелец (Owner)
Запись (Write)
100
Владелец (Owner)
Исполнение (Execute)
40
Группа (Group)
Чтение (Read)
20
Группа (Group)
Запись (Write)
10
Группа (Group)
Исполнение (Execute)
4
Все (Global)
Чтение (Read)
2
Все (Global)
Запись (Write)
1
Все (Global)
Исполнение (Execute)
 
Например, если на сервер загружается изображение в качестве контента, то оно должно быть доступно всем посетителям. Значит, ему можно присвоить атрибут-маску 644 (значение в восьмеричной системе). Это позволит администратору читать/записывать, а посетителям только читать.
 
Папки на сервере тоже имеют атрибут-маску. Если папка содержит общедоступные файлы, например, изображения или файлы формата DOC, RTF, XLS, … с прайсами и прочими документами, то такой папке следует присвоить атрибут-маску 755. Тогда Администратор сможет в эту папку записывать файлы, читать их и исполнять, а остальные пользователи смогут лишь читать и исполнять.
 
Не рекомендуется ставить атрибут 777, поскольку тогда в такую папку абсолютно любой пользователь сможет загрузить на сервер любой файл, даже PHP и выполнить его. Такая маска упростит жизнь хакеру, если он вознамерится совершить с вашим сайтом дефейс (глумление) или некие действия от имени вашего сервера, например, рассылка спама.
 
При аплоаде назначить файлу атрибут-маску можно сразу же после выполнения функции move_uploaded_file. Для этой операции предусмотрена команда chmod (http://ru.wikipedia.org/wiki/Chmod) и команда umask (http://ru.wikipedia.org/wiki/Umask).
 
Функция chmod изменяет режим доступа к файлу или каталогу. Её формат:
 
chmod ( полное имя файла, режим )
 
Функция umask позволяет получить и изменить маску режима создания пользовательских файлов. Формат:
 
umask ( маска )
 
Например, так:
 
if(is_file( $upload_name )){
$oldumask = umask(0);
// Ставим дружественные права на загруженный файл
chmod( $upload_name, 0744 );
umask( $oldumask );
}
 
В данном примере выполняется проверка существования файла по пути $upload_name. Если файл существует, то командой umask получаем и сохраняем старое значение маски режима создания файла, аргументом 0 (нуль) разрешаем изменение маски доступа к файлу последующей командой chmod. Далее вносим изменения командой chmod, а затем возвращаем прежний режим командой umask.
 
Новая для нас команда is_file определяет, существует ли файл и является ли обычным файлом. В данном случае применяем её в качестве аналога функции file_exists(), которая возвращает true, если файл существует.
 
ВАЖНО! Следует помнить, что при аплоаде файлов, имена которых содержат символы кириллицы, файлы на сервер будут записаны с нечитаемыми именами. Это сделает их совершенно недоступными для веб. И даже зайдя на сервер через FTP-клиент, вы навряд ли сможете их удалить.
 
Это происходит вследствие того, что веб-сервер в отличие от домашнего компьютера не поддерживает кириллицу в именах файлов. Удалить такие файлы с некорректными именами удастся разве что только из менеджера файлов в C-panel хостинга.
Поэтому следует сразу предусмотреть средства для автоматической транслитерации имени загруженного файла в латиницу прежде, чем будет сделан вызов функции move_uploaded_file.
 
Это может быть некая пользовательская функция с названием, например, RusToLat. При этом она должна вызываться раньше, чем функция basename получит имя исходного файла. Пример:
 
<?
if(count($_FILES)){
$upload_name = $_SERVER["DOCUMENT_ROOT"]."/".
basename(RusToLat($_FILES['userfile']['name']));
if(move_uploaded_file($_FILES['userfile']['tmp_name'], $upload_name))
echo "Файл успешно загружен в папку ".dirname($upload_name)."n";
else echo "Ошибка загрузки файла.n";
}
?>
 
Иногда (на очень "продвинутых") хостингах имена исходных файлов поступают в скрипт в кодировке UTF-8 и при этом веб-программист не имеет доступа ко всем необходимым настройкам сервера Apache, чтобы решить эту проблему.
Тогда приходится изобретать универсальный способ, который обеспечивает гарантированную работу скрипта в любых условиях. Для преобразования Unf-8 в кодировку Win-1251 можно составить пользовательскую функцию с именем, например, Utf8ToWin и применять её в связке с RusToLat например, так RusToLat(Utf8ToWin(…)).
 
Продолжение следует…
 
© Владислав Демьянишин
 
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ. Предлагаю также посетить Марья искусница - сайт о рукоделии (http://mariya-iskusnica.ru).
 

Журнал > Программирование > PHP и WEB для новичков (HTML, JavaScript, PHP, MySQL) > PHP и WEB для новичков (часть 11): Загрузка файлов на сервер
 
 
 
2340
 
ВКонтакте
Facebook
 
 
 
На главную страницу На предыдущую страницу На начало страницы
 
 
Украинский портАл Украина онлайн Рейтинг@Mail.ru Рейтинг Сайтов YandeG Rambler's Top100