Php и Upload (Загрузка файлов на сервер) Multipartформы
![]()
|
PHP и Upload (Загрузка файлов на сервер) Multipart-формы Загрузка фаилов на сервер осуществляется пользователями сети интернет довольно часто, а именно:
Загрузка файла на сервер осуществляется с помощью multipart-формы, в которой есть поле загрузки файла. В качестве параметра enctype указывается значение multipart/form-data: Вот так примерно будет выглядеть приведенная multipart-форма (вы можете попробовать с ее помощью посмотреть результат работы multipart-форм, загрузив какой-нибудь файл небольшого размера на сервер): Multipart-формы обычно используют метод передачи POST. Как видно из предыдущего примера, данная форма имеет два поля: • Поле выбора файла для закачки ;
Обработка multipart-форм Прежде, чем приступить к написанию скрипта обработки multipart-формы, нужно отредактировать файл конфигурации php.ini, чтобы разрешить загрузку файлов на сервер. Конфигурационный файл PHP php.ini имеет три параметра, связанные с загрузкой файлов на сервер:
HTTP;
Если ваш веб-сервер работает под управлением операционной системы Linux, то нужно перезапустить сервис: ![]() service httpd restart Как же PHP обрабатывает multipart-формы? Получив файл, он сохраняет его во временном каталоге upload_tmp_dir, имя файла выбирается случайным образом. Затем он создает четыре переменных суперглобального массива $_FILES. Этот массив содержит информацию о загруженном файле. Переменные, определенные для загруженных файлов, зависят от версии PHP и текущей конфигурации. Суперглобальный массив $_FILES доступен начиная с PHP 4.1.0. В случае, если конфигурационная директива register_globals установлена значением on, дополнительно будут объявлены переменные с соответствующими именами. Начиная с версии 4.2.0 значением по умолчанию для опции register_globals является off. Содержимое массива $_FILES для нашего примера приведено ниже. Обратите внимание, что здесь предполагается использование имени uploadfile для поля выбора файла, в соответствии с приведенной выше multipart-форме. Разумеется, имя поля может быть любым.
После завершения работы скрипта, временный файл будет удален. Это означает, что мы должны его скопировать в другое место до завершения работы скрипта. То есть алгоритм работы сценария загрузки файла на сервер такой: Если кнопка "Submit" нажата, то файл уже будет загружен на сервер и его имя будут в переменной $_FILES['uploadfile']['name']. В этом случае скрипт должен сразу скопировать файл с именем $_FILES['uploadfile']['tmp_name']
Используйте только функцию копирования copy(), а не перемещения, поскольку:
выведено сообщение об ошибке. Предположим, нам нужно загрузить файл в каталог uploads, который находится в корневом каталоге веб-сервера (в каталоге DocumentRoot).
воспользуемся оператором @: @mkdir("uploads", 0777);
copy($_FILES['uploadfile'] ['tmp_name'],"uploads/".basename($_FILES['uploadfile'] ['name'])); В Linux все намного сложнее - нам нужно учитывать права доступа к каталогу uploads. Скорее всего в таком случае, функция mkdir() не сработает, так как у нас нет прав на запись в каталог DocumentRoot (обычно это /var/www/html или /home/httpd/html). Зарегистрируйтесь в системе как пользователь root, создайте каталог uploads и измените его владельца и права доступа следующим образом: // Создаем каталог uploads mkdir uploads
тоже apache: chown apache:apache uploads
chmod 1777 uploads Размер файла можно ограничить, при желании можно отредактировать файл .htaccess и ограничить доступ к каталогу uploads - указать или конкретных пользователей, которым можно обращаться к каталогу, или IP-адреса. Вот теперь можно загружать файлы на сервер. Пишем PHP скрипт загрузки файлов на сервер php
![]() $uploadfile = $uploaddir.basename($_FILES['uploadfile'] ['name']);
if (copy($_FILES['uploadfile'] ![]() ['tmp_name'], $uploadfile)) {echo " Файл успешно загружен на сервер";![]() } ![]() else { echo "Ошибка! Не удалось загрузить файл на се рвер!"; exit; }
![]() echo "Информация о загруженном на сервер файле: h3>"; ![]() echo " Оригинальное имя загруженного файла: ". ![]() $_FILES['uploadfile']['name']." "; echo " Mime-тип загруженного файла: ". ![]() $_FILES['uploadfile']['type']." "; echo " Размер загруженного файла в байтах: ". $_FILES['uploadfile']['size']." "; ![]() echo " Временное имя файла: ".$_FILES['uploadfile'] ['tmp_name']." "; ?> Загрузка на сервер нескольких файлов Загрузку нескольких файлов можно реализовать используя, например, различные значения name для тега input. Также предусмотрена возможность автоматического получения организованной в массив информации о нескольких одновременно загружаемых файлах. Для реализации такой возможности используйте тот же синтаксис отправки массива из HTML-формы, что и для множественных полей select и checkbox: В случае, если такая форма была отправлена, массивы $_FILES['userfile'], $_FILES['userfile']['name'], и $_FILES['userfile']['size'] будут инициализированы (точно так же, как и $HTTP_POST_FILES для PHP 4.1.0 и более ранних версий). Если конфигурационная директива register_globals установлена значением on, также будут инициализированы сопутствующие глобальные переменные. Каждая из таких переменных будет представлять собой численно индексированный массив соответствующих значений для принятых файлов. Предположим, что были загружены файлы /home/test/some.html и /home/ test/file.bin. В таком случае переменная $_FILES['userfile']['name'][0] будет иметь значение some.html, а переменная $_FILES['userfile']['name']
Переменные $_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'] [0], $_FILES['userfile']['size'][0] и $_FILES['userfile']['type'][0] также будут инициализированы. Заключение: Как видите, организовать загрузку файлов на сервер не так сложно. Сложнее обеспечить необходимый уровень безопасности, так как загрузка файлов на сервер может использоваться злоумышленниками для атаки на сервер. PHP и Cookies Cookies - это механизм хранения данных броузером удаленного компьютера для идентификации возвращающихся посетителей и хранения параметров веб-страниц (например, переменных). Приведем пример использования Cookies на конкретном примере. Предположим, нам нужно написать счетчик посещения сайта. Нам нужно знать, какое число посещений сайта осуществлялось каждым конкретным посетителем. Данную задачу можно решить двумя способами. Первый из них заключается в ведении учета IP-адресов пользователей. Для этого нужна база данных всего из одной таблицы, примерная структура которой такая: IP-адрес Число посещений
Когда пользователь заходит на сайт, нам нужно определить его IP-адрес, найти в базе данных информацию о его посещениях, увеличить счетчик и вывести его в браузер посетителя. Написать обработчик (скрипт) подобной процедуры несложно. Однако при использовании такого метода у нас появляются проблемы следующего характера:
Можно использовать второй способ, который намного легче в реализации и более эффективен. Мы устанавливаем в Cookie переменную, которая будет храниться на диске удаленного пользователя. Эта переменная и будет хранить информацию о посещениях. Она будет считываться скриптом при обращении посетителя к серверу. Выгода такого метода идентификации очевидна. Во-первых, нам не нужно хранить множество ненужной информации о IP-адресах. Во-вторых, нас не интересуют динамические IP-адреса, поскольку данные о своих посещениях хранятся конкретно у каждого посетителя сайта. Теперь понятно, для чего мы можем использовать Cookie - для хранения небольшой по объему информации у клиента (посетителя) сайта, например: настройки сайта (цвет фона страниц, язык, оформление таблиц и.т.д.), а также другой информации. Файлы Cookies представляют собой обыкновенные текстовые файлы, которые хранятся на диске у посетителей сайтов. Файлы Cookies и содержат ту информацию, которая была в них записана сервером. Программирование Cookies Приступим к программированию Cookies. Для установки Cookies используется функция SetCookie(). Для этой функции можно указать шесть параметров, один из которых является обязательным:
Пример установки Cookies: php
![]() SetCookie("Test","Value");
![]() ?> При использовании Cookies необходимо иметь в виду, что Cookies должны устанавливаться до первого вывода информации в браузер (например, оперетором echo или выводом какой-либо функции). Поэтому желательно устанавливать Cookies в самом начале скрипта. Cookies устанавливаются с помощью определенного заголовка сервера, а если скрипт выводит что-либо, то это означает, что начинается тело документа. В результате Cookies не будут установлены и может быть выведено предупреждение. Для проверки успешности установки Cookies можно использовать такой метод:
if (SetCookie("Test","Value")) echo " Cookiesуспешно установлены!";?> Функция SetCookie() возвращает TRUE в случае успешной установки Cookie. В случае, если Cookie установить не удается SetCookie() возвратит FALSE и возможно, предупреждение (зависит от настроек PHP). Пример неудачной установки Cookie: ![]()
![]() echo "Hello"; ![]()
![]() if (SetCookie("Test","Value")) echo " Cookieуспешно установлен!";else echo " Cookie установить не удалось!";![]()
![]() ?> ![]() Cookie установить не удалось, поскольку перед посылкой заголовка Cookie мы вывели в браузер строку "Hello". Чтение значений Cookies Получить доступ к Cookies и их значениям достаточно просто. Они хранятся в суперглобальных массивах и $_COOKIE и $HTTP_COOKIE_VARS. Доступ к значениям осуществляется по имени установленных Cookies, например: echo $_COOKIE['my_cookie'];
Пример установки Cookie и последующего его чтения: ![]()
setcookie("test","Hello",time()+3600);
?> В рассмотренном примере при первом обращении к скрипту устанавливается Cookie "test" зо значением "hello". При повторном обращении к скрипту будет выведено значение Cookie "test", то есть строка "Hello". При чтении значений Cookies обращайте внимание на проверку существования Cookies, например, используя оператор isset(). Либо путем подавления вывода ошибок опереатором @ А вот пример, как построить счетчик числа загрузок страницы с помощью Cookies: ![]()
![]() if (isset($_COOKIE['Mortal'])) $cnt=$_COOKIE['Mortal'] +1; ![]() else $cnt=0; ![]()
![]() setcookie("Mortal",$cnt,0x6FFFFFFF); ![]()
![]() echo " Вы посещали эту страницу ".@ $_COOKIE['Mortal']." раз "; ![]() ?> Удаление Cookies Иногда возникает необходимость удаления Cookies. Сделать это несложно, необходимо лишь вновь установить Cookie с идентичным именем и пустым параметром. Например: ![]()
![]() ?> ![]() Установка массива Cookies и его чтение Вы может установить массив Cookies, используя квадратные скобки в именах Cookies [], а затем прочитать массив Cookies и значения этого массива: ![]()
![]() setcookie("cookie[2]", "Второй"); setcookie("cookie[3]", "Третий"); ![]()
![]() if (isset($_COOKIE['cookie'])) { ![]() foreach ($_COOKIE['cookie'] as $name => $value) {echo "$name : $value "; ![]() ![]() } ![]() } ![]() ?> Преимущества использования Cookies неоспоримы. Однако существуют и некоторые проблемы их использования. Первая из них заключается в том, что посетитель может блокировать прием Cookies браузером или попросту удалить все Cookies или их часть. Таким образом, мы можем иметь некоторые проблемы в идентификации таких посетителей. О регулярных выражениях. Регулярные выражения - мощный гибкий инструмент для синтаксического анализа текста в соответствии с определенным шаблоном. Шаблон - строка символов, спецсимволов и модификаторов, описывающих правила, которым должен соответствовать разбираемый текст. Синтаксис регулярных выражений. Это раздел о том, из чего состоят шаблоны. Любой шаблон должен быть ограничен символами-ограничителями. В качестве таких символов можно использовать любой не буквенно-цифровой символ кроме '\'. Не рекомендуется использовать в качестве ограничителей и другие специальные символы, в виду того их использование внутри шаблона станет неудобным. Предпочтительнее всего использовать символ /, потому что он не выполняет никаких специальных функций. Символ, используемый как ограничитель шаблона внутри шаблона должен экранироваться. Пример: '/pattern/i' - соответствует строке, в которой есть слово pattern. i - это модификатор. Забегая вперед, скажу, что он означает регистронезависимое сравнение. 1 - Спецсимволы. Сначала о них, потому что мне будет легче описать остальное. \ - символ экранирования. Пример: '/qwe\/rty/' - соответствует строке, в которой есть qwe/try. Символ
^ - символ начала данных. $ - символ конца данных. Пример: '/^pattern$/' - Соответствует строке, точно совпадающей с словом pattern. Т.е. с буквы p строка начинается и после n заканчивается. . - любой символ, кроме перевода строки. Но естьмодификатор, при использовании которого перевод строки тоже относится к "любым" символам. Пример: '/pat.ern/' - Соответствует и строке, содержащей pattern, или patdern, или pat3ern... [] - внутри этих скобок перечисляются символы, любой один символ из которых может стоять на данном месте. Это называется символьным классом. Спецсимволы, написанные в [] ведут себя немного по-другому. Это я напишу. Пример: '/pat[aoe]rn/' - под соответствие попадут только строки, содержащие patarn, patorn или patern. | - Или. Пример ниже. () - подмаска.
+ - одно или более вхождений. Пример: '/as+(es|du)?.*r/' - Буква а, потом одна или больше букв s, после этого сочетание es или du может быть один раз, а может м ни разу, потом любое количество любых символов и буква r. Здесь же скажу про еще одно значения символа ?. Метасимвол звездочка по умолчанию жадный (и другие тоже). Это значит, что в нашем примере вот этой части '.*r' будет соответствовать, например, подстрока asdrfsrsfdr. Как видно, до последней буквы r в нее попало еще две. Вот эту жадность можно выключить. Т.е. шаблон станет соответствовать только подстроке asdr. До первого r. Для этого надо в до того места где необходимо отключить жадность поставит модификатор (?U). Вот еще одно применение символам ? и (). {a,b} - количество вхождений предшествующего символа или подмаски от а до б. Если б не указан, считается, что верхней границы нет. Например, * - то же самое, что {0,}. ? - то же, что {0,1}. {5,7} - 5,6 или 7 повторений.
Пример: [^da] - соответствует любому символу кроме d и a. Пример: [^^] - соответствует любому символу кроме ^. Пример: [d^a] - соответствует любому символу из перечисленных трёх. [\^da] - то же самое. В последнем примере, как видно символ стоит не в начале перечисления и свою метафункцию теряет. И экранировать его, кстати, тоже тут не надо. - - внутри символьного класса означает символьный интервал. Пример: [0-9a-e] - соответствует любому символу от 0 до 9 и от a до e. Если в символьном классе надо перечислить сам символ дефиса, то следует либо заэранироватьего, либо разместить перед ]. Осторожно в символьном классе надо использовать символ \. Если его поставить перед ], она окажется заэкранирована. Также окажется заэкранированным любой символ, который может быть заэкранирован. Иначе символ \ является обычным символом. Символ $ тоже является обычным символом внутри символьного класса. И скобки тоже. б) Символ \. Одна из его функций - снятие специального значения с спецсимволов. А другая, наоборот придание специальных функций обычным символам. \cx - ctrl + x. На месте x может быть любой символ. \e - escape. \f - разрыв страницы. \n, \r, \t - это нам и так привычно. Перевод строки, возврат каретки и табуляция. \d - любой символ, означающий десятичную цифру. \D - любой символ, не означающий десятичную цифру. \s - любой пробельный символ. \S - не пробельный. \w - любоя цифра, буква или знак подчеркивания. \W - любой символ, но не \w. \b - граница слова. Можно использовать вместо \w\W или \W\w или ^\w или \w$ \B - не граница слова. Две последние конструкции не соответствуют никаким реальным символам. \xHH - символ с шестнадцатиричным кодом HH. x - это именно буква икс. \DDD - символ с восьмиричным кодом DDD. Или ссылка на подмаску. По поводу ссылки на подмаску: '/([0-9]{2,3}).\1/' - 2 или 3 символа от 0 до 9, потом любая последовательность символов и те же 2 или 3 конкретных символа, которые соответствовали подмаске. То есть строка 'as34sdf34' - подойдет. Там 34, и там. А 'sd34dg32' - нет. Если анализатор находит \x, он считывает максимальное количество последующих символов, которые могут быть шестнадцатиричным числом. Максимальное - это не больше двух. Если из три, то считается два, если меньше - то сколько есть. Если анализатор находит \0, он поступает аналогично. Только считывает не 16ричные, а восмеричные цифры. До двух штук. То есть \0\x\0325 означает два символа с кодом ноль, символ с восьмеричным кодом 32 и пятерка. Если после слеша стоит отличная от нуля цифра, то ту посложнее. Вот напишем такую вещь: \40. Если в шаблоне есть 40 подмасок, то это будет воспринято как ссылка на 40ю подмаску. Сороковую - в десятичной системе счисления. Если же подмасок меньше, то это будет воспринято как символ с восьмеричном кодом 40. \040 - всегда символ с кодом и восьмеричным 40. \7 - всегда ссылка на подмаску. \13 - в зависимости от ситуации.
99. 2 - Обычные символы. Это символы, не являющиеся специальными. 3 - Модификаторы. Указываются они либо в скобках, например так: (?Ui), либо после закрывающего символа '/pattern/Ui'. i - регистронезависимость. U - инвертирует жадность. m - многострочный поиск. s - если используется, то символ . соответствует и переводу строки. Иначе она ему не соответствует. x - заставляет игнорировать все неэкранированные пробельные символы, если они не перечислены в символьном классе. Удобно, когда энтерами и пробелами вы хотите навести удобночитаемость в регулярке. При использовании модификаторов, можно использовать знак '-' для отключения модификатора. (?m-i) - Bключаем многострочный поиск и отключаем регистронезависимый. Здесь надо сказать, что все модификаторы что-то включают. Или отключают, если указаны с минусом. А вот U инвертирует. Т.е. если была жадность включена, он выключит без всяких минусов. 4 - Утверждения. Утверждения - это проверки касательно символов, идущих до или после текущей позиции сопоставления. Например, \b - это утверждение, что предыдущий символ словесный, а следующий - нет, либо наоборот. Но это как бы встроенное утверждение, а мы тут сейчас свои собственные научимся писать. Утверждения касательно последующего текста начинаются с (?= для положительных утверждений и с (?! для отрицающих утверждений. Утверждения касательно предшествующего текста начинаются с (? <= для положительных утверждений и (?Например, '/(? (?<=\d{3})(? Утверждения могут быть вложенными, причем в произвольных сочетаниях: (?<=(?
По-моему, этого достаточно: (?(condition)yes-pattern|no-pattern) Пример: (?(?=\d)u|p). (?=\d) - это условие. Мы утверждаем, что после этого места идет цифра. Если оно истинно, то на данном месте должна стоять буква u. Иначе - p. 5 - Комментарии. Комментарии начинаются с (?# и продолжаются до ближайшей закрывающей скобки. Так же как /* */ в PHP - без учета вложенности. Функции PHP для работы с регулярными выражениями. mixed preg_match ( string $pattern, string $subject [, array $matches [, int $flags [, int $offset]]] ) Ищет в заданном тексте subject совпадения с шаблоном pattern . Если совпадение не найдено - вернет false.
Похожая функция preg_match_all с теми же параметрами. Она отыскивает все совпадения в то время как preg_match - только первое. array preg_split ( string $pattern, string $subject [, int $limit [, int $flags]] ) Возвращает массив, состоящий из подстрок заданной строки subject, которая разбита по границам, соответствующим шаблону pattern.
mixed preg_replace ( mixed $pattern, mixed $replacement, mixed $subject [, int $limit] ) Выполняет поиск в строке subject совпадений с шаблоном pattern и заменяет их на replacement. В случае, если параметр limit указан, будет произведена замена limit вхождений шаблона; в случае, если limit опущен либо равняется -1, будут заменены все вхождения шаблона. $replacement может содержать ссылки на подмаски шаблона. Таким образом, можно поменять в строке местами части, соответствующие двум разным подмаскам. mixed preg_replace_callback ( mixed $pattern, callback $callback , mixed $subject [, int $limit] ) Выполняет поиск по регулярному выражению и замену с использованием функции обратного вызова. Пример: function rnd_replace($matches) { ![]() if ($matches[1] > 'c') ![]() return '('.$matches[1].'->'.rand(0, 9).')'; ![]() else ![]() return $matches[1]; } $src = 'sd4vaf345g534fgh43kj3'; $res = preg_replace_callback('/ (\D)/', 'rnd_replace', $src); echo $res ![]() ?> Все нецифры, которые больше, чем c, будут заменены сами увидите на что. |