Пример (краткий) формы и скрипта для проверки и записи файла на сайт. Вопросы.

Гриша К.

Новичок
Пример (краткий) формы и скрипта для проверки и записи файла на сайт. Вопросы.

Здравствуйте.
Изучая и используя найденную информацию по загрузке файлов на сайт, в итоге получилась следующая форма для загрузки файлов и соответсвующий скрипт для проверки и записи файла на сайт (только для зарегестрированных пользователей).

Уважаемые модераторы. Я надеюсь приведенный пример кода, вы не посчитаете таким большим, чтобы закрыть тему. Я посторался сделать код максимально кратким и удобным для чтения. И возможно данный пример с комментариями, будет кому-то полезен.

-------------------------------
form.php?city=1264 - пример формы для загрузки файлов на сайт
PHP:
/* Извещаю сервер о то, что посылаю файл enctype="multipart/form-data" */
<form enctype="multipart/form-data" method="post" action="form.php?city=1264">
        /* Максимальный размер загружаемого файла ~ 1 МБ */
        <input type="hidden" name="MAX_FILE_SIZE" value="1000000">
        <input type="file" name="userfile">
</form>
-------------------------------
form.php?city=1264 - пример скрипта для проверки и обработки файлов
PHP:
/* Использую следующие данные о файле */ 
$userfile = $_FILES['userfile']['tmp_name']; // Временное имя 
$userfile_name = $_FILES['userfile']['name']; // Исходное имя; 
$userfile_size = $_FILES['userfile']['size']; // Размер; 
$userfile_type = $_FILES['userfile']['type']; // MIME-тип; 
$userfile_error = $_FILES['userfile']['error']; // Код ошибки

/* userfile_error - Проверка ошибок. Вывод сообщений об ошибках */
if ($userfile_error > 0) {
    switch ($userfile_error) {
        case 1: $error='Превышение размера файла в php.ini';  break;
        case 2: $error='Превышение размера файла в форме';  break;
        case 3: $error='Загружена только часть файла';  break;
        case 4: $error='Файл не загружен';  break;
    }
}
/* Проверка MIME-типа. Для IE - pjpeg, для остальных - jpeg */
elseif ($userfile_type != 'image/pjpeg' && $userfile_type != 'image/jpeg')  {
    $error = 'Файл не формата jpeg';
}
else {  
/* Помещаем файл туда, куда нужно */
    $upfile = './'.$_GET['city'].'.jpg';
    /* Проверяем существует ли такой файл */
    if (file_exists($upfile)) { 
        $error = 'Файл уже существует';
        }
        /* Проверяем, что обрабатываемый файл действительно загружен и не является локальным */
        elseif (is_uploaded_file($userfile)) {
            if (filesize($userfile) > 2000000) { 
                $error = 'Файл превышает размер в 2 МБ'; 
            }
            elseif (!move_uploaded_file($userfile, $upfile)) {
                $error = 'Невозможно переслать файл в каталог назначения';
            }
            else {					
                /* Здесь у меня осуществляется запись данных в БД, если записать не удалось, 
                то вывожу об этом сообщение и удаляю файл unlink($upfile);
                В противном случае пересылаю пользователя на нужную страницу для просмотра файла 
                */                
                header('Location: [url]http://[/url]'.$_SERVER['HTTP_HOST']);
                exit;
            }
        else {
            $error = 'Возможна атака через загрузку файла.';
        }
    }
}
-------------------------------
Вопросы:

(1) На сайт предполагается загружать фотграфии. Например мой фотоаппарат делает снимки (без приближения) имеющие расширение 2560 x 1920 (ширина x высота), максимальный размер файла ~ 2,5 МБ. Если сжимать такую фотографию, например в photoshop, то ее уменьшинные размеры соответсвуют размерам расширения экрана в windows (800 x 600, 1024 x 768 и т.д.), в итоге такие фотографии для просмотра я вывожу в формате 330 x 247, а при нажатии на них открывается оригинал.
Я вот хотелбы узнать рекомендуются ли ограничения на какое-то максимальное расширение и размер загружаемого файла? И возможно вы знаете, все ли фотографии соотвествуют при сжатии размерам экрана в windows и будут ли они пропорциональны формату 330 x 247.

(2) Если будут загружаться файлы размером 2,5 МБ, стоит ли увеличить время выполнения сценария: ini_set('max_execition_time', 120);?

(3) Я читал, что раньше формат jpeg соотвествовал MIME-типу image/jpeg, я пробовал делать проверку типа файла так ($userfile_type != 'image/pjpeg' || $userfile_type != 'image/jpeg'), но тогда файлы *.jpeg не проходят такую проверку, стоит ли проверять тип файла 'image/jpeg' и если да, как это сделать правильно.

(4) Напишите пожалуйста учтены ли все основные проверки загружаемого файла, и возможно вы увидите какие-то критические ошибки в приведенных примерах.
 

master_x

Pitavale XXI wieku
насчет третьего пункта. такой майм-тип (image/pjpeg) посылает только IE.
 

Гриша К.

Новичок
master_x, спасибо большое, проверил в OPERA, так и есть.
Sluggard, спасибо за ссылку, сейчас разбираюсь, есть очень хорошая дополнительная информация.

И сразу хотелбы спросить, раз разные броузеры по разуному определяют тип файла, это необходимо учесть, я пробую это делать так, но ни как немогу понять, почему это не проходит:
PHP:
elseif ($userfile_type != 'image/pjpeg' || $userfile_type != 'image/jpeg' ) { 
    $error = 'Файл не формата jpeg'; 
}
При таком условии файлы *.jpeg не загружаются. Ну не как я немогу понять почему, яже поставил или '||', т.е. если $userfile_type не равняется этому 'image/pjpeg' или этому 'image/jpeg', то вывожу ошибку. Если хоть одному равняется, то ошибку не вывожу. Либо я очень сильно туплю.
 

Sluggard

Новичок
А теперь переводим написанные тобой условия на человеческий язык и пытаемся усердно вдумываться в течении 10 минут...
 

Гриша К.

Новичок
ksnk, спасибо большое. Я даже непробовал ствить 'И', думая что так буде по любому не верно. Ну вот даже сейчас немогу понять эту логику.
Sluggard, я как раз сижу и думаю об этом, и уже не первый раз, и не как не могу в голове это обработать, т.е. я думаю так, что при '||', должно все работать. Ну бывает же такая тупость в голову залезает и никак от нее не избавиться.
Сейчас в сам скрипт на верху это добавлю.

-~{}~ 15.03.06 22:18:

Вот я выяснил, что есть такие директивы в php.ini, которые влияют на загрузку файла (благодаря ссылки отсавленной Sluggard):

upload_max_filesize = 2M ; Максимальный размер загружаемых файлов
max_execution_time = 30 ; Максимальное время выполнения скриптов
max_input_time = 60 ; Максимально допустимое время в секундах для получения входящих данных
memory_limit = 8M ; Максимальный объём памяти в байтах, который разрешается использовать скрипту
post_max_size = 8M ; Максимальный допустимый размер POST-данных

Я попытался их изменить при помощи функции ini_set(), в итоге изменить удалось только директиву 'max_execution_time'
Ниже я приведу код, при помощи которого я пытался их изменить.

Так как у меня нет опыта загрузки файлов на сервер, я прошу ваших советов, по поводу:

(1) Стоит ли пытаться изменить upload_max_filesize = 2M, либо просто требовать от пользователей соотвествовать этим требованиям (Вот попадется пользователь у которого файл 2,5M - и он не умеет изменять его расширение, тогда файл он не закачает - Или не надо об этом думать)

(2) Если не получается изменить upload_max_filesize = 2M или вообще если не стоит этого делать, учитывая то, что ни одной дерективы не получается изменить, стоит ли 'max_execution_time' увеличить до 60 секунд.

PHP:
echo '<br />upload_max_filesize:<br/>';
echo ini_set('upload_max_filesize', '3M').'-';
echo ini_get('upload_max_filesize');

echo '<br />max_execution_time:<br/>';
echo ini_set('max_execution_time', 100).'-';
echo ini_get('max_execution_time');

echo '<br />max_input_time:<br/>';
echo ini_set('max_input_time', 100).'-';
echo ini_get('max_input_time');

echo '<br />memory_limit:<br/>';
echo ini_set('memory_limit', '10M').'-';
echo ini_get('memory_limit');

echo '<br />post_max_size:<br/>';
echo ini_set('post_max_size', '10M').'-';
echo ini_get('post_max_size');
 

_RVK_

Новичок
Ограничения должны быть на размер файла. Сколько? Определи сам для себя. Но не только путем установки значения в php.ini а проверкой после загрузки файла, и перед копированием из временной директории. upload_max_filesize конечно тоже оставить надо, что бы тебе пару терабайт не закачали.

стоит ли 'max_execution_time' увеличить до 60 секунд
Не нужно.

Насчет пропорцианальности. Не нужно на это полагаться. Я бы советовал уменьшать ширину до заданной, а высоту пропорционально. Обрати внимание на слово выделенное жирным.
 

Гриша К.

Новичок
_RVK_, спасибо большое за разъяснения.

К сожалению получается, что максимальный размер файла умтановленный в php.ini нельзя поменять, например при помощи ini_set(). А как я прочитал на php.net, нельзя будет загрузить файл на сайт, больше чем в php.ini
Вот это все меня забутало. Так что буду использовать максимально допустимый размер в 2 МБ. Хотя файл размером 1,9 МБ уже не загрузить.

Проверку размера файла, я тогда вот здесь еще добавлю (if ($userfile_size > 2000000)):

PHP:
/* Проверяем, что обрабатываемый файл действительно загружен и не является локальным */ 

$userfile = $_FILES['userfile']['tmp_name'];
$userfile_size = $_FILES['userfile']['size'];

//...
        elseif (is_uploaded_file($userfile)) {
            if ($userfile_size > 2000000) {
                $error = 'Файл превышает размер в 2 МБ';
            }
            elseif (!move_uploaded_file($userfile, $upfile)) { 
                $error = 'Невозможно переслать файл в каталог назначения'; 
            } 
            else {    
                //...          
            }
 

_RVK_

Новичок
echo $_FILES['userfile']['size'];
Проверку размера файла, я тогда вот здесь еще добавлю:
Это значение можно подделать. Но в твоем случае это не существенно, если пренебречь случаем когда кто-то (например админ сервера) установит upload_max_filesize больше приемлемого для тебя размера. Лучше все же проверять с помощью [m]filesize[/m].
 

Гриша К.

Новичок
_RVK_, спасибо вам, хорошо, что вы такое разъяснение дали. Буду использовать filesize().

Уже посмотрел как работает. Добавлю в код ксрипта выше.

PHP:
if (filesize($userfile) > 2000000) { 
       $error = 'Файл превышает размер в 2 МБ'; 
       }
 

alekciy

Новичок
Re: Пример (краткий) формы и скрипта для проверки и записи файла на сайт. Вопросы.

Автор оригинала: Гриша К.
Вопросы:

(1) На сайт предполагается загружать фотграфии. .....

Я вот хотелбы узнать рекомендуются ли ограничения на какое-то максимальное расширение (разрешение?) и размер загружаемого файла? И возможно вы знаете, все ли фотографии соотвествуют при сжатии размерам экрана в windows и будут ли они пропорциональны формату 330 x 247.
Я тоже вот движок галереи пишу (http://alekciy.h16.ru/foto_gallery/foto_gallery.php), но я на стадии проектирования сразу отказался от понятия "стандартного коэффициента отношения сторон" (анг. ratio) и подгонки фоток под определенный размер. Вот у тебя к примеру фотик делат фотки с коэффициентом 1.33..., а у меня 1.5 (3072х2048), а ведь у других пользователей фотографии могу быть с другими отношениями сторон.
Правда до конца идею пока не реализовал. В настоящий момент работает так: пользователь грузит фотку, скрипт смотрит размеры фотографии и рассчитывает коэф. этой фотки, создает маленькую превьюшку 105х70 точек и ложет её на сервер. Большая превьюшка создается динамически при клике пользователя по малой превьшке. Если фотка горизонтальная, то аккуратно вписывается в размер 450 x 300 пикселей и выдаеться клиенту, если же вертикальная, вписывается в 300 x 375 пикселей.
По хорошему, в будующем, мне думается, что размер большой превьюшки пользователь сможет сам задавать в настройках своего профиля. Т.е. есть желание уйти от строга заданного коэффициента.

Насчет же тех, кто сам не может изменить свои файлы до нужного размера, так это вполне по силам сделать скрипту который автоматически будет делать ресайз до нужных габаритов (в том числе и подрезку).
 

Гриша К.

Новичок
alekciy, посмотрел ваш сайт. У нас в итоге получается разные с вами задачи, в том смысле, что у меня должны быть полюбому фотграфии одного размера, что по ширине, что по длинне. Такова идея проекта и по другому просто нельзя.

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

Вы знаете я посмотрел, вот например ваше изображение 3072 х 2048, если обе его части разделить на 9,3, то получится 330 x 220, то вот незнаю насколько сильно будет заметно искажение, если его преобразовать в 330 x 247.

Конечно получается сложный вопрос. Озадачили вы меня сильно.
 

alekciy

Новичок
Если делать через обрезку (или дополнении 220 точек до 247, но тогда будет на фотке черный бордюр), то никакого искажения не будет. Если же вписываться в 330х247 то без искажений ни как. Тут либо одно, либо другое, иначе ни как.

З.Ы. Кстати фотку закиньте на тоже мыло, с которого придет письмо. Потому и оценим уровень искажения, ведь у меня все приводиться к коэ. 1.5.
 

Гриша К.

Новичок
alekciy, фотографию пока не получил. Присылайте. Я вам сразу свою пришлю.

При отображение маленьких фотографий, у меня скрипт сжимает фотографию таким образом, чтобы она не привышала ее границ 330 x 247, но соответсвенно с соблюдение пропорций.
=================================
Я вот посмотрел, что при сжатии фотографии 1393 x 1100, получаю 313 x 247 - т.е фотография по ширине меньше фотографий формата 2560 x 1920.

Также я представил, что сжимая фотографию 3072 х 2048, например на 9.3 получится 330 x 220 - т.е фотография по высоте меньше фотографий формата 2560 x 1920.
=================================

В итоге получится, что как ни крути, придется подстариваться под то, что фотографии, могут не соответсвовать одной ширине или оной высоте.

----------------
И получается, что у вас при добавлении фотографии, получается так, что если он к примеру имеет разрешение 3072 х 2048 и размер 3 МБ (3000000 байт), а у вас к примеру максимльный допустимый размер фотографий 2 МБ, то получится, что ваш скрипт сожмет эту фотографию до размера 2 МБ и разрешения 2048 x 1365.
Но ведь при таком варианте фотография будет отображена с искажениями, нельзя же уменьшать разрешение фотографии на 1px и чтобы при каждом таком уменьшении фотография отображалась одинаково.
Либо можно так сжимать фтографию, чтобы она совершенно не имела искажей, вот точно как оригинал. но чуть чуть поменьше?

-~{}~ 16.03.06 15:59:


alekciy, я добавил фотографию в вашу галерею, и оказывается я неправильно вас понял, у вас скрипт автоматически не уменьшает фото. У вас стоит ограничение в 100 КБ и все.
Я вот подумал, что я сделаю так, в ворме добавления фотографий, я размещу информацию о том, что для того чтобыуменьшить размер фотографии, можно скачать такую-то програмку (найду какую-нибудь хорошую и маленькую : ) и при помощи ее пользователь сможет уменьшить ее объем, а потом записать, а потом добавить на сайт.
А позже буду думать о том, чтобы научиться кооректно сжимать фотографии, до нужных размеров и так их записывать на сайт, если конечно это вообще возможно реализовать, как-то с трудом это предстовляю.
 

bgm

&nbsp;
Автор оригинала: Гриша К.

- Я даже непробовал ствить 'И', думая что так буде по любому не верно. Ну вот даже сейчас немогу понять эту логику.

- я думаю так, что при '||', должно все работать.
Почитай про булеву алгебру - будет полезно, и, может быть, начнёшь понимать больше чем сейчас.
 

Гриша К.

Новичок
bgm, спасибо за ссылку. Щас открыл ее, и закрыл. Другой работы много, будет время и желание почитаю.
 

alekciy

Новичок
>у вас скрипт автоматически не уменьшает фото. У вас стоит
>ограничение в 100 КБ и все.
Именно так. На сколько мне известно, по такому принципу работают все галереи. Если дать пользователю возможность загрузки больших файлов, то он может попросту закачать кучу файлов и забить дисковое пространство хоста. Есть и другое соображение. Если пользователю дать возможность загрузки больших файлов, то при закачке его просто может обрубить сервер от закачки, а не скрипт (при превышении времени данного на upload или выполнение скрипта), получить и файл не загружен, и пользователь не понимает, в чем дело. Если пользователь хочет загружать фотографии, то он должны обладать хотя бы элементарными понятиями об обработке фотографий. Используя тот же Microsoft Office Picture Manager из пактета Office 2003 изменить размер фотографии дело одного клика.

Именно исходя из этих соображений и не предусмотрена автоматическая "ужимка" фотографии. Хотя реализовать этот достаточно просто. Достаточно внести некоторые изменения в скрипт и воспользоваться функцией imagecopyresampled. Но я счел, это такая возможность не нужна. А что было бы интересно попользоваться такой возможностью?
Ну если интересно, то могу на твою учетку (давай на "ты"? не люблю я эти все формальности), прикрутить возможность загрузки больших файлов и "ужимки" их да заданного размера (кстати до кокого? 2560 x 1920? Многова-то вообще-то). Узнаешь заодно, как GD фотки пережимает. Добавить? (неужели какая функция для пользователей может понадобиться?!)
 

Гриша К.

Новичок
alekciy, спасибо за разъяснения. Да давай на ты. У меня просто в привычку вошло, совсеми начинать общаться на вы.

Принцип отображения фотографий в моей галеери очень своеобразный, когда я сделаю ее я вам покажу.
После добавления фотографии в раздел, пользователь не сможет загрузить еще одну, пока она не будет проверена модератором.
Если сжимать фотографию до 100 килобайт, то разрешение будет совсем маленькое, а мне необходимо, что бы при клике на фотографию отображалась фотографию хорошего качества, и разрешения минимум 800x600, но я думаю что максимально разрешение для ширины и высоты можно было сделать 1600 x 1200, т.е фотография тогда к примеру может быть в формате 1600 x 1000 или 1400 x 1200.


alekciy, я не знаю к примеру, как сделать так, чтобы если пользователь загружает большую фотографию, ее к примеру можно было сжать. Почему я вообще об этом задумался, просто ведь если у пользователя такой же фотоаппарат как у меня и фотография у него будет 2,5 МБ, то в мое сейчашнее ограничение он не впишется, и бдет думать что же такое и еще решит забить на это.
Если у вас есть время, и желание, сделать некоторые добавления, примерно для такой реализации, я был бы очень рад и благодарен вам. Посмотрели бы мнение и соображение пользователей о такой реализации.
 
Сверху