| Основы закачки файловСогласно протоколу HTTP файлы можно закачивать двумя способами:
 
 Наиболее распространеный POST метод, PUT метод в настоящее время почти не используется. Чтобы броузер передал файл нужно поместить на страницу такой HTML код
 
 <form enctype="multipart/form-data" method="post" action="upload_script.php">
 <input type="hidden" name="MAX_FILE_SIZE" value="1000">
 Выберите файл: <input name="имя_поля" type="file">
 <input type="submit" value="Послать файл">
 </form>
 
 
 
 ОБЯЗАТЕЛЬНО нужно указывать <form enctype="multipart/form-data" method="post"...> и очень желательно <input type="hidden" name="MAX_FILE_SIZE" value="XXXX"> причем ДО поля ввода файла. Когда эти условия выполнены, можно писать скрипт который будет обрабатывать закачку файлов.
 
 <?php
 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("Файл с именем <b>".$filename."</b> уже существует.
 Переименуйте файл или удалите его с сервера");
 }
 }
 
 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). Выключите его для определенных файлов:
 <Files upload.php><br>
 CharsetDisable On<br>
 </Files>
 
Не закачиваются большие файлы. Причин может быть несколько, если не выполняется хоть одно из условий, файл не закачается:
 
 Размер файла больше $_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)
 
Пользователь сидит за прокси который запрещает передачу 
 |