Следующая статья: Переменные PHP внутри функций
Немного теории. Это нужно, для понимания что и как работает.
- вы в броузере указываете файл для загрузки на сервер;
- броузер передает выбранный файл на сервер;
- PHP-интерпретатор на сервере записывает полученный файл во временную директорию. Причем, имя, под которым записывается файл, может быть абсолютно случайным. Это только под Windows PHP пишет файл с именами подобными <b>PHP2<b>.
- Нам, в принципе, вовсе не обязательно знать под каким именно именем загруженный файл хранится во временной директории. Почему не надо знать?
- Потому что, вполне достаточно того, что PHP «знает». И, в любом случае, после завершения работы скрипта, этот файл удаляется.
- Вы говорите PHP, что загруженный файл надо скопировать из временной директории туда, куда хотите.
На этом, сам процесс «аплоада» можно считать завершенным.
Что вы потом сделаете с этим файлом, вопрос другой.
И еще: все трудности под Win32 связанные с «непонимаем» системой конструкции вида «\PHP2»; (кто сталкивался, поймет) кроются в файле php.ini (php3.ini) Лично у меня, это выглядит так (получено опытным путем):
upload_tmp_dir="f:tmp" - php.ini
С такими настройками, никаких проблем я не замечал. Попробуйте.
Теперь про ограничение размера загружаемого файла. Конечно, и в php.ini есть параметр upload_max_filesize, можно ограничить и размер и тип указанием соответствующих параметров в теге FORM, но, в любом из этих случаев мы получим ошибку, которую не сможем обработать. Что не здорово. Поэтому, удобней ограничивать размер в самом скрипте.
НО: РАЗМЕР файла невозможно узнать до ПОЛНОЙ загрузки файла на сервер. Никаким способом.
Также, при uploade, до ЗАВЕРШЕНИЯ загрузки, файл хранится в памяти, потом пишется во временную директорию, и, еще раз напомню, сразу удаляется из temp по завершению работы скрипта. Вообщем, с помощью PHP не получится сделать индикатор загрузки файлов.
Итак, сначала у нас файл upload.html примерно такого вида.
<html> <head> <title>Upload</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> <!-- обратите внимание на enctype!!! --> <input type="file" name="file1" /><br /> <input type="file" name="file2" /><br /> <input type="submit" name="upload" value="Загрузить" /> </form> </body> </html>
Теперь, сам скрипт.
<?php
$max_size=65535;
// максим. размер в БАЙТАХ
$type_1='application/x-zip-compressed';
$type_2='text/plain';
// типы файлов, которые мы хотим принимать
$path='/home/test/frob';
// Путь / каталог, куда сохраняем файлы
if (($file1=='none')&&($file2=='none'))
{ echo 'Не выбрано ни одного файла!'; exit; }
if ($file1_size>$max_size)
{ echo 'Неверный размер! Файл '.$file1_name.' НЕ загружен.'; }
elseif (($file1_type!=$type_1) and ($file1_type!=$type_2))
{ echo 'Неверный тип! Файл '.$file1_name.' ('.$file1_type.') НЕ загружен.'; }
else
{ copy($file1,$path.'/'.$file1_name);
echo 'Вы загрузили файл '.$file1_name.'. Этот файл сохранен в каталоге '.$path.'<br />';
echo 'Размер файла - '.$file1_size.' байт<br />';
echo 'Тип файла - '.$file1_type.'<br /><br /><br /><br />';
}
if ($file2_size>$max_size)
{ echo 'Неверный размер! Файл '.$file2_name.' НЕ загружен.';
}
elseif (($file2_type!=$type_1) and ($file2_type!=$type_2))
{ echo 'Неверный тип! Файл '.$file2_name.' НЕ загружен.';
}
else
{ copy ($file2,$path.'/'.$file2_name);
echo 'Вы загрузили файл '.$file2_name.'. Этот файл сохранен в каталоге '.$path.'<br/>';
echo 'Размер файла - '.$file2_size.' байт<br />';
echo 'Тип файла - '.$file2_type.'<br />';
}
?>
Итак, если Вы не удосужились открыть Manual, рассказываю (хотя, FAQ то он, конечно, FAQ, но чтение manual'ов никто не отменял):
В форме есть поле с type=file и именем file1. При аплоаде, у нас возникают переменные:
- $file1 - имя файла во временной директории;
- $file1_name - исходное имя файла;
- $file1_type - MIME тип файла;
- $file1_size - размер файла;
Так, осталось рассмотреть случай, когда PHP работает в safe-mode. То есть, если вы сделали все как написано, а вам говорят
Safe-mode restriction is effect… Или, про то, что невозможно выполнить команду copy() - попробуйте copy() заменить на move_uploaded_file().
Но, невозможность выполнить copy() может крыться и просто в том, что у PHP-процесса не хватает прав на запись в указанную вами директорию. В этом случае, вам проще всего спросить у своего администратора, какие права должны быть на директорию, в которую хочется записывать файлы.
Фу-у-у-у…
Последний штрих: на самом деле, если вам следует загрузить несколько файлов, не стоит пользоваться приведенной конструкцией. Лучше, обозвать поля для ввода файлов именем, например, file[], а потом разбирать полученный массив file[] уже.
Возможные глюки
Итак, вы сделали форму для аплоада файлов, вы сделали скрипт, который принимает загруженные файлы, но теперь возникла следующая проблема:
Картинки загружаются, но не показываеются. Бинарные файлы загружаются, но не запускаются (или, не распаковываются, если это архив).
Основная причина данной проблемы - Russian Apache.
Именно он (то есть, web-server) перекодирует все что ни попадя. Соответственно, после такой перекодировки, в файлах оказываются замещенными (перекодированными) некоторые символы. Что избежать подобного есть несколько решений:
1) В директории, где лежит скрипт для Upload'a делаем файл .htaccess в котором пишем:
CharsetDisable On
2) В файл httpd.conf дописать строки:
<Location /> CharsetRecodeMultipartForms Off </Location>
Обычно, этого вполне достаточно для решения проблемы.
Upload и PHP4
в PHP4 работа с upload`ами стала несколько иной. Теперь вся информация о залитых файлах хранится в массиве $HTTP_POST_FILES для примера:
если у нас в форме было так: <input type="file" name="screenshot"> то информацию о файле надо смотреть здесь:
$HTTP_POST_FILES['screenshot']['name']
Оригинальное имя файла. Например «screen1.jpg»
$HTTP_POST_FILES['screenshot']['type']
mime type файла. Например «image/gif».
$HTTP_POST_FILES['screenshot']['size']
Размер файла в байтах
$HTTP_POST_FILES['screenshot']['tmp_name']
Временное имя файла на сервере.