Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: ошибка отправки заголовка при отсутствии файла в copy()
 
 автор: aetern   (15.07.2009 в 22:25)   письмо автору
 
 

После формы
<input type="file"  name="filename">
скрипт выполняет поочередно функции:

copy($_FILES['filename']['tmp_name'], $file);

а затем
header("Location: index.php");


но в случае, если в форме файл не добавлен выдается ошибка:
Warning: copy() [function.copy]: Filename cannot be empty in ...
Warning: Cannot modify header information - headers already sent by ...

если же файл добавлен - ошибки - нет.

Но самое главное, ошибка выдается только на сервере хостинг-провайдера.
При работе дома - ошибки нет.
Может дело в каких-то настройках.

  Ответить  
 
 автор: Trianon   (15.07.2009 в 22:32)   письмо автору
 
   для: aetern   (15.07.2009 в 22:25)
 

Своим постом Вы не задаете ни одного вопроса.
Лишь констатируете факты.
Факты верные, да.

  Ответить  
 
 автор: aetern   (15.07.2009 в 22:36)   письмо автору
 
   для: Trianon   (15.07.2009 в 22:32)
 

Виноват.
Вопрос:
Какие настройки необходимо изменить для ликвидации указанных ошибок?
И в результате чего они возникают?
Спасибо.

  Ответить  
 
 автор: AcidTrash   (15.07.2009 в 22:42)   письмо автору
 
   для: aetern   (15.07.2009 в 22:36)
 

Перед функцией копирования проверяйте данные этого поля на наличие значения, или в самой форме через JS.

  Ответить  
 
 автор: aetern   (15.07.2009 в 22:46)   письмо автору
 
   для: AcidTrash   (15.07.2009 в 22:42)
 

Проверить-то можно, но вопрос остается прежним, что вызывает ошибки?
Функция copy() находится в классе и не хотелось бы вносить в него изменения.

  Ответить  
 
 автор: sim5   (16.07.2009 в 00:07)   письмо автору
 
   для: aetern   (15.07.2009 в 22:46)
 

Вот здесь о ваших ошибках: http://ru2.php.net/manual/ru/features.file-upload.php

  Ответить  
 
 автор: aetern   (16.07.2009 в 00:17)   письмо автору
 
   для: sim5   (16.07.2009 в 00:07)
 

Спасибо хоть на этом, только с английским у меня проблема. Попробую поизучать код на указанном форуме.
А разве проблема не в системных настройках?

  Ответить  
 
 автор: sim5   (16.07.2009 в 00:21)   письмо автору
 
   для: aetern   (16.07.2009 в 00:17)
 

А что там на английском, как только примеры? Главная ваша ошибка, это неверная логика загрузки файлов на сервер, и не та функция для этой задачи (copy).

  Ответить  
 
 автор: Trianon   (16.07.2009 в 00:14)   письмо автору
 
   для: aetern   (15.07.2009 в 22:36)
 

ага. по пунктам.

>После формы<input type="file" name="filename">скрипт выполняет поочередно функции:
copy($_FILES['filename']['tmp_name'], $file);

это само по себе ошибка. функцию copy не применяют для этих целей. информация в мануале по copy. Исправить.

>а затем header("Location: index.php");
Это ошибка наведена предыдущей

>но в случае, если в форме файл не добавлен выдается ошибка:
>Warning: copy() [function.copy]: Filename cannot be empty in ...

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

>Warning: Cannot modify header information - headers already sent by ...
если же файл добавлен - ошибки - нет.
Если файл добавлен - система не выдает диагностику, а значит header еще может отправить заголовок.

>Но самое главное, ошибка выдается только на сервере хостинг-провайдера.
Выдается - только на нем. Присутствует - в любом случае.

>При работе дома - ошибки нет.
При работе дома ошибка не видна!

>Может дело в каких-то настройках.
Да. Настройка output buffering слегка сглаживает картину. Ошибку логики она не отменяет.

  Ответить  
 
 автор: aetern   (16.07.2009 в 00:24)   письмо автору
5.8 Кб
 
   для: Trianon   (16.07.2009 в 00:14)
 

руководствовался логикой по книге "ООП на PHP" (М.Кузнецова и И.Симдянова) класс class.field.file.php
Файл свой прилагаю.

  Ответить  
 
 автор: aetern   (17.07.2009 в 20:04)   письмо автору
 
   для: Trianon   (16.07.2009 в 00:14)
 

Тему подчистили, а вот вопросы остались!

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

Не могу я понять почему это происходит.
Вот код отвечающий за проверку (находится в класе).
Что сдесь не так?!? Все ведь очень просто!

!empty
оно ведь и в африке
!empty
!!!

<?php
      
if(!empty($this->value)) // value - это $_FILES
      
{
        
// Проверяем, не является ли файл скриптом PHP 
        // или Perl, html, если это так преобразуем его в формат .txt
        
$extentions = array("#\.php#is",
                            
"#\.phtml#is",
                            
"#\.php3#is",
                            
"#\.html#is",
                            
"#\.htm#is",
                            
"#\.hta#is",
                            
"#\.pl#is",
                            
"#\.xml#is",
                            
"#\.inc#is",
                            
"#\.shtml#is"
                            
"#\.xht#is"
                            
"#\.xhtml#is");
        
// Заменяем русские символы на транслит
        
$this->value[$this->name]['name'] = 
              
$this->encodestring($this->value[$this->name]['name']);
        
// Извлекаем из имени файла расширение
        
$path_parts pathinfo($this->value[$this->name]['name']);
        
$ext ".".$path_parts['extension'];
        
$path basename($this->value[$this->name]['name'],$ext);
        
$add $ext;
        foreach(
$extentions AS $exten
        {
          if(
preg_match($exten$ext)) $add ".txt"
        }
        
$path .= $add
        
$path str_replace("//","/",$dir."/".$prefix.$path);
        
// Перемещаем файл из временной директории сервера в
        // директорию /files Web-приложения
        
if (copy($this->value[$this->name]['tmp_name'], $path))
        {
          
// Уничтожаем файл во временной директории
          
@unlink($this->value[$this->name]['tmp_name']);
          
// Изменяем права доступа к файлу
          
@chmod($path0644);
        }
      }
?>

  Ответить  
 
 автор: Trianon   (17.07.2009 в 20:17)   письмо автору
 
   для: aetern   (17.07.2009 в 20:04)
 

Ну, в $_FILES обычно всегда что-то есть. Даже если самого файла и нет.
Но почему Вы применяете именно copy() , мне всё равно не понять.

  Ответить  
 
 автор: aetern   (17.07.2009 в 20:24)   письмо автору
 
   для: Trianon   (17.07.2009 в 20:17)
 

Вы рекомендуете move_uploaded_file()

  Ответить  
 
 автор: Trianon   (17.07.2009 в 20:25)   письмо автору
 
   для: aetern   (17.07.2009 в 20:24)
 

Не я. Мануал рекомендует.

  Ответить  
 
 автор: aetern   (17.07.2009 в 20:28)   письмо автору
 
   для: Trianon   (17.07.2009 в 20:25)
 

Чтоже там такого!? Ушел читать...

  Ответить  
 
 автор: sim5   (18.07.2009 в 03:06)   письмо автору
 
   для: aetern   (17.07.2009 в 20:28)
 

А раньше, когда я вам давал ссылку почитать, вы значит все таки поленились, и не читали? А в мануале как раз многое сказано и об copy(), и о нежелательности именовать файлы именами пользователя, и многое еще.... Вот вам о загрузке файлов сводная информация:

PHP версии 3 не имел функции move_uploaded_file(), поэтому до выхода четвертой версии использовалась функция copy(), которая до сих пор находится в документации и пользуется популярностью. Но нежелательно использовать copy() при закачке файлов, т.к. возможны проблемы. Copy() вообще не будет работать при включенном open_basedir! При safe_mode=On чтобы использовать copy(), нужно установить на временную папку того же владельца, что и выполняет скрипт, тоесть загрузка файлов будет невозможна, если у вас несколько пользователей (как и должно быть в случае виртуальных доменов). Кроме того copy() не выполняет проверку файла на существование.

Возможные проблемы при загрузке файлов

1. Закачка файлов запрещена - file_uploads=Off в php.ini.

2. Нету прав на папку - измените владельца на пользователя под которым запущен скрипт или поставьте на папку chmod 0777

3. Целевая директория имеет другого владельца, чем под которым запущен PHP, когда safe_mode=On. Это повсеместно распространенный случай для шарового хостинга, когда пользователь Апача для примера www или nobody, тогда как доступ по FTP, например, для pupkin. Выхода два:
а) обратиться в службу поддержки для настройки одинаковых юзеров на FTP и Apache (для вашего виртуального домена);
б) папку для загрузки создать из скрипта под Апачем и поставить на неё 'chmod 0777'. Тогда вы сможете работать из скриптов обходя safe_mode запреты и редактировать файлы по FTP.

4. Нету прав на upload_tmp_dir (настройка в php.ini). Поставьте chmod 0777 на эту папку.

5. Файлы могут быть испорченными если под Апачем запущены некоторые модули, например mod_charset (также известный как Russian Apache). Выключите его для определенных файлов:
<Files upload.php>
CharsetDisable On
</Files>

6. Не закачиваются большие файлы. Причин может быть несколько, если не выполняется хоть одно из условий, файл не закачается:
а) размер файла больше $_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)
3) время выполнения скрипта превысило таймаут для CGI (Консоль IIS)

7. Пользователь сидит за прокси, который запрещает передачу.

8. Вы использовали другой способ закачки, например, сокращенный синтаксис, при том что register_globals=Off или старая версия PHP, или ещё хуже - использовали copy() вместо move_uploaded_file().

9. Неправильно работает $_FILES[$field_name]['type']. Это не глюк PHP, этот параметр передаётся броузером, так что никогда не полагайтесь на него.

10. Проблемы с закачкой файлов не из под броузера (не URI encoded форма). В большинстве случаев для этого понадобится использовать $HTTP_RAW_POST_DATA.

11. Проблемы с закачкой файлов нулевой длины. Суть проблемы не в том, что файлы не закачиваются, а в том, что невозможно определить закачался ли файл на самом деле. Многие проверяют статус закачки через $_FILES[$field_name]['size'], но как в случае когда файл не закачался, так и в случае пустого файла, переменная будет равна 0. Если пользователь сам напечатает имя несуществующего файла в поле броузера, он передастся как файл нулевой длины. Проверить это средствами PHP нельзя.

12. magic_quotes_gpc=On и stripslashes на Win платформе создаст проблемы с получением имен файлов, так, например, $_FILES[$field_name]['name'] всё-таки должен содержать двойные бек-слеши.

13. Неправильные параметры переданы в move_uploaded_file().

  Ответить  
 
 автор: Trianon   (17.07.2009 в 20:28)   письмо автору
 
   для: Trianon   (17.07.2009 в 20:25)
 

Я же , в свою очередь, тоже рекомендую, но другое.
а) начинать работу с массивом $_FILES с анализа ключа 'error'
б) никогда не применять клиентское имя файла (элемент 'name') для сохранения файла на сервере.

  Ответить  
 
 автор: aetern   (17.07.2009 в 20:56)   письмо автору
 
   для: Trianon   (17.07.2009 в 20:28)
 

>а) начинать работу с массивом $_FILES с анализа ключа 'error'
Спасибо за совет, я вообще забыл о существовании $_FILES['userfile']['error']

>б) никогда не применять клиентское имя файла (элемент 'name') для сохранения файла на сервере.
Знаю, знаю, но все равно спасибо.

>Ну, в $_FILES обычно всегда что-то есть
Это была ключевая фраза всей темы, что же Вы раньше-то молчали?
Проблему решил так:
if(!empty($this->value[$this->name]['tmp_name'])) { }


Видимо, вера в знание и в безошибочность авторов вышеуказанной книги затмила глаза ;-).
Спасибо всем кто участвовал и отдельное Trianon.

  Ответить  
 
 автор: Trianon   (17.07.2009 в 21:06)   письмо автору
 
   для: aetern   (17.07.2009 в 20:56)
 

>Это была ключевая фраза всей темы, что же Вы раньше-то молчали?

Мы с Sim5 охрипли уже бороться с продвинутыми аплоадерами...
Плюс к тому, модератор очередной раз выдал рекомендацию помолчать.

  Ответить  
 
 автор: aetern   (17.07.2009 в 21:14)   письмо автору
 
   для: Trianon   (17.07.2009 в 21:06)
 

Непонятно осталось лишь одно, почему дома ошибка была не видна?
Я работаю с Денвером.

  Ответить  
 
 автор: Trianon   (17.07.2009 в 21:21)   письмо автору
 
   для: aetern   (17.07.2009 в 21:14)
 

потому что диагностику нотайсов блокируете.
Нотайс об отсутствии поля tmp_name и name тут же бы нарыв вскрыл.

Впрочем, блокируете Вы её по рекомендации софттайма, который этот фреймворк написал, и который (фреймворк) при включенных нотайсах вообще взбеситься может. Так что тут палка о двух концах....

[М.! Имей совесть... ]

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования