Лекція № 9
Тема: Завантаження файлів
План
Multipart-форми та їх опис.
Обробка multipart-форм.
Multipart-форми і їх опис
Завантаження файлів на сервер по протоколу HTTP здійснюється набагато чаші, чим ви можете подумати:
- Web-інтерфейси поштових сервісів дозволяють додати до листа вкладення, а для цього потрібно спершу завантажити файл на сервер, а тільки після цього додавати до листа.
- Інтерактивні фотогалереї і фотоальбоми просто не можуть існувати без механізму завантаження файлів.
- Web-інтерфейси засобів управління контентом, які використовуються для управління сайтом, дозволяють завантажувати файли на сервер у вказаний каталог.
Завантаження файлу на сервер здійснюється за допомогою так званої multipart-форми, в якій є поле завантаження файлу, — <input type=file>. При цій якості параметра enctype указується значення multipart/form-data:
<form action=upload.php method=POST enctype=multipart/form-data>
<input type=file name=UFile>
Ім'я файлу на сервері <Input type=text name=Filename>
<input type=submit name=upload value=3агрузить>
</form>

Як виглядає Multipart-форма можна подивитися на мал
Multipart-форма
Multipart-форми зазвичай використовують метод передачі POST. Як видно з вищенаведеного прикладу дана форма зазвичай має два поля:
Поле файлу вибору файлу для закачування <INPUT type=File>.
Поле вказівки імені файлу, яке він повинен буде мати на сервері <INPUT type=text>.
Сценарій завантаження файлів на сервер.
Обробка multipart-форм
Перш, ніж приступити до написання сценарію завантаження файлу, потрібно відредагувати файл конфігурації /etc/php.ini, щоб вирішити завантаження файлів. Відкрийте файл конфігурації і знайдіть секцію File uploads. У ній будуть три параметри:
file_uploads = On — вирішує завантаження файлів на сервер по протоколу HTTP.
upload_tmp_dir = /tmp — встановлює каталог для тимчасового зберігання завантажених файлів.
upIoad_max_fiIesize — 2М — встановлює максимальний об'єм файлів які можуть бути завантажені.
Якщо ваш Web-сервер працює під управлінням операційної системи Linux, потрібно перезапустити сервіс:
service httpd restart
Під Windows 9x/NT нічого робити не потрібно, оскільки РНР не вбудовується, як модуль в Apache.
Як же РНР обробляє Multipart-форми? Отримавши файл, він зберігає його в тимчасовому каталозі upload_tmp_dir, ім'я файлу вибирається випадковим чином. Потім він створить чотири глобальних змінних:
$UFile (так називається поле завантаження файлу) — містить ім'я файлу I в тимчасовому каталозі, наприклад, /tmp/phpJ6r5eR.
$UFiIe_name — ім'я файлу до його відправки на сервер, наприклад | /home/den/water.png або c:\water.png.
$UFiIe_size — розмір прийнятого файлу в байтах.
$UFiIe_type — тип прийнятого файлу (якщо браузер зміг його опреде- ] лити), наприклад, image/png, image/jpeg, text/html.
Після завершення роботи сценарію тимчасовий файл буде видалений. Це означає, що ми повинні його скопіювати в інше місце до завершення роботи сценарію. Тобто алгоритм роботи сценарію завантаження файлів такий:
Якщо не натиснута кнопка "Submit" — відобразити форму завантаження файлу. 1
Якщо кнопка "Submit" натиснута, то файл вже буде завантажений на сервер і j його ім'я буде в змінній $UFile. В цьому випадку сценарій винен відразу скопіювати файл з ім'ям $UFile у який-небудь каталог (ви повинні мати права запису в цей каталог). Ви НЕ можете зберегти ім'я файлу в Cookies і скопіювати його при наступному запуску сценарію — файлу з ім'ям $UFile вже не буде — це звичайний тимчасовий файл і він буде видалений при завершенні роботи сценарію. Копіювання проводиться функцією copy():
copy($UFile, "/var/www/html/uploads/".basename($UFile_name) );
Потрібно використовувати тільки функцію копіювання. Використовувати функцію переміщення немає ніякого сенсу, оскільки:
Тимчасовий файл буде видалений автоматично.
Якщо тимчасовий каталог знаходиться на іншому носієві, ми отримаємо повідомлення про помилку.
Припустимо, що нам потрібно завантажити файл в каталог uploads, який знаходиться в кореневому каталозі Web-сервера (каталозі DocumentRoot).
// Про всяк випадок створюємо каталог. Якщо він вже створений,
// повідомлення про помилку буде
// пригнічене оператором @ @mkdir("uploads",0777) ;
// Копіюємо файл з /tmp в uploads
// Ім'я файлу буде таким же, як до відправки на сервер
copy($UFile, "uploads/".basename($UFile_name));