Основы: HTTP Files Upload - закачка файлов на сервер через браузер

Основы закачки файлов
Согласно протоколу HTTP файлы можно закачивать двумя способами:
- POST методом
- PUT методом
Наиболее распространеный POST метод, PUT метод в настоящее время почти не используется. Чтобы броузер передал файл нужно поместить на страницу такой HTML код
Если вам необходима разработка сайта Винница, тогда обращайтесь за помощью в компанию ABCname
Выберите файл:
Выберите файл:
ОБЯЗАТЕЛЬНО нужно указывать и очень желательно причем ДО поля ввода файла.
Когда эти условия выполнены, можно писать скрипт который будет обрабатывать закачку файлов.
function doUpload($field_name, $overwrite=false, $uniquename=false){
if (!is_array($field_name)) $field_name=Array($field_name);
#-------- FILE UPLOAD -----------------
// место хранения файлов
$storage="/home/www/public_html/uploads/";
// маленькие проверки на будущие глюки
$flag = (bool) ini_get("safe_mode");
if ($flag||(!strstr($_SERVER['SERVER_SOFTWARE'], 'win'))){
if (getmyuid()!=fileowner($storage)){
die("Safe mode uncompatibililty. Check owner for '".$storage"'");
}
}
// разрешенные для закачки расширения (типы) файлов
$allowed=array(
'jpg',
'gif',
'png',
'pdf',
'doc',
'txt',
'rtf'
);
foreach ($field_name as $field_i){
// максимальный размер файла. В любом случае он не может быть
// больше чем upload_max_filesize=??M в php.ini (2Мб)
// а также post_max_size=??M (8Мб)
$maxsize=61440; // 60Kб
// считываем имя закачиваемого файла
$filename=$_FILES[$field_i]['name'];
// считываем размер закачиваемого файла
$filename=$_FILES[$field_i]['size'];
// считываем расширение файла
$fileext=strtolower(substr(strrchr($filename,"."),1));
// запрещаем закачку неразрешенных типов, например PHP скриптов!!
if(!in_array($fileext, $allowed)){
die("Недопустимый тип файла");
}
// запрещаем закачку слишком больших файлов
if($filesize>$maxsize){
die("Слишком большой файл");
}
// считываем имя файла, который закачан во временную папку
// upload_tmp_dir= в файле php.ini
$tmpfname=$_FILES[$field_i]['tmp_name'])
// исправляем имя файла, удаляем недопустимые символы, пробелы.
$filename = ereg_replace("[^a-z0-9._]", "",
str_replace(" ", "_",
str_replace("%20", "_", strtolower($name))));
if ($filename=""){
die("Недопустимое имя файла. Только английские буквы, цифры и '_'!");
}
// полный путь к закачке файла
$filepath=$storage;
if ($uniquename){
$filepath=$filepath.time()."_";
}
$filepath=$filepath.$filename;
if (is_uploaded_file($tmpfname) {
// если $overwrite!=true проверяем нету ли уже такого файла
if (!$overwrite){
if (file_exists($filepath)){
die("Файл с именем ".$filename." уже существует.
Переименуйте файл или удалите его с сервера");
}
}
move_uploaded_file($tmpfname, $filepath)
or die("Ошибка закачки файла: ".$filename);
// Если пользователь Апача и FTP разные, например nobody и pupkin,
// то чтобы иметь доступ по FTP (по умолчанию выставляется 0600)
// поставьте 0644 или 0666 если хотите также перезаписывать по FTP
@chmod($filepath, 0644);
}
}
}
#------------- END FILE UPLOAD ----------
}
// вызвать функцию
doUpload('имя_поля');
// закачать несколько файлов сразу
doUpload(Array('имя_поля1','имя_поля2'));
// если нужно перезаписывать существующий файл
doUpload('имя_поля', true);
// если нужно сохранить существующий файл
// будет создано новое имя, н: pic.jpg -> 989181984_pic.jpg
doUpload('имя_поля', false, true);
?>
PHP версии 3 не имел функции move_uploaded_file() поэтому до выхода четвертой версии исполльзовалась функция copy() которая до сих пор находится в документации и пользуется популярностью. КРАЙНЕ НЕЖЕЛАТЕЛЬНО использовать copy() при закачке файлов, т.к. возможны многие глюки. copy() вообще не будет работать при включенном open_basedir!! В safe_mode=On чтобы использовать copy() нужно установить на временную папку того же ВЛАДЕЛЬЦА что и выполняет скрипт, тоесть аплоад будет невозможно делать если у вас несколько пользователей (как и должно быть в случае виртуальных доменов). Кроме того copy() не выполняет проверку файла на существование, не возвращает
Возможные глюки
- file_uploads=Off в php.ini. Закачка файлов запрещена
- Нету прав на $storage="/home/www/public_html/uploads/". Измените chown на пользователя под которым запущен скрипт или поставьте на папку chmod 0777
- Целевая директория имеет другого владельца чем под которым запущен PHP, когда safe_mode=On. Это повсеместно распространенный случай для шарового хостинга, когда пользователь Апача для примера www или nobody, тогда как доступ по FTP, например, для pupkin. Выхода два:
- Долбить службу поддержки для настройки одинаковых юзеров на FTP и Apache (для вашего виртуального домена).
- Папку для загрузки создать ИЗ скрипта под Апачем и поставить на неё 'chmod 0777'. Тогда Вы сможете работать из скриптов обходя safe_mode запреты и редактировать файлы по FTP.
- Нету прав на upload_tmp_dir=; (настройка в php.ini). Поставьте chmod 0777 на эту папку.
- Файлы могут быть испорченными если под Апачем запущены некоторые модули, например mod_charset (Также известный как Russian Apache). Выключите его для определенных файлов:
CharsetDisable On- Не закачиваются большие файлы. Причин может быть несколько, если не выполняется хоть одно из условий, файл не закачается:
- Размер файла больше $_POST['MAX_FILE_SIZE']
- Размер файла больше upload_max_filesize=2M (php.ini)
- Размер файла больше post_max_size=8M (php.ini)
- Размер файла больше LimitRequestBody (httpd.conf)
- Исчерпана дисковая квота или на upload_tmp_dir= или на целевую директорию
- Время выполнения скрипта превысило max_execution_time= (php.ini)
- Время выполнения скрипта превысило Timeout 30 (httpd.conf)
- Время выполнения скрипта превысило таймаут для CGI (Консоль IIS)
- Пользователь сидит за прокси который запрещает передачу
- Вы использовали ДРУГОЙ способ закачки, чем в этой статье, например сокращенный синтаксис, при том что register_globals=Off или старая версия PHP или, ещё хуже - использовали copy() вместо move_uploaded_file().
- Неправильно работает $HTTP_POST_FILES[$field_name]['type']. Это не глюк PHP, этот параметр передаётся броузером, так что НИКОГДА не полагайтесь на него.
- Проблемы с НЕброузерной закачкой файла (Не URI encoded форма). В большинстве случаев для этого понадобится использовать $HTTP_RAW_POST_DATA
- Проблемы с закачкой файлов нулевой длины. Суть проблемы не в том что файлы не закачиваются, а в том что невозможно определить закачался ли файл на самом деле. Многие люди проверяют статус закачки через $HTTP_POST_FILES[$field_name]['size'] но как в случае когда файл не закачался, так и в случае пустого файла, переменная будет равна 0. Если пользователь сам напечатает имя несуществующего файла в поле броузера, он передастся как файл нулевой длины. Проверить это средствами PHP нельзя.
- magic_quotes_gpc=On и stripslashes на Win платформе создаст проблемы с получением имен файлов, так например $HTTP_POST_FILES[$field_name]['size'] всё-таки должен содеражть двойные бек-слеши.
- Неправильные параметры переданы в move_uploaded_file(). Там должно быть что-то вроде:
// правильный синтаксис
move_uploaded_file(
'/var/php_tmp_upload/userfile.jpg',
'/home/pupkin/public_html/userfile.jpg'
);
// неправильный синтаксис
move_uploaded_file(
'userfile.jpg',
'/home/pupkin/public_html/userfile.jpg'
);
?>
Работу данных скриптов можно проверить заказав хостинг г. Винница в нашей компании.