Множинне завантаження файлів PHP. Приклад завантаження файлів на сервер (upload) мовою php

Multipart-форми

  • Веб-інтерфейси поштових сервісів, які дозволяють додавати до листа додаток (attach), а для цього потрібно спочатку завантажити файл на сервер, і тільки після цього його можна додавати до листа;
  • Інтерактивні фотогалереї та фотоальбоми, які не можуть існувати без механізму завантаження файлів на сервер;
  • Портали безкоштовного програмного забезпечення, які використовують для обміну файлами різних програм, тощо.

Завантаження файлу на сервер здійснюється за допомогою multipart-форми, в якій є поле завантаження файлу. Як параметр enctype вказується значення multipart/form-data :



Ось так приблизно виглядатиме наведена multipart-форма (ви можете спробувати з її допомогою подивитися результат роботи multipart-форм, завантаживши якийсь файл невеликого розміру на сервер):

Multipart-форми зазвичай використовують метод передачі POST. Як видно з попереднього прикладу, ця форма має два поля:

  • Поле вибору файлу для закачування;
  • Поле вказівки імені файлу, яке він повинен мати на сервері.

Обробка multipart-форм

Перш ніж приступити до написання скрипта обробки multipart-форми, потрібно відредагувати файл конфігурації php.ini, щоб дозволити завантаження файлів на сервер.

Конфігураційний файл PHP php.ini має три параметри, пов'язані із завантаженням файлів на сервер:

  • file_uploads = On - дозволяє завантаження файлів на сервер за протоколом HTTP;
  • upload_tmp_dir=/tmp – встановлює каталог для тимчасового зберігання завантажених файлів;
  • upload_max_filesize=2M - встановлює максимальний обсяг файлів, що завантажуються.

Якщо ваш веб-сервер працює під керуванням операційної системи 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-форми. Зрозуміло, ім'я поля може бути будь-яким.

  • $_FILES["uploadfile"]["name"] - ім'я файлу до його відправки на сервер, наприклад, pict.gif;
  • $_FILES["uploadfile"]["size"] - розмір прийнятого файлу в байтах;
  • $_FILES["uploadfile"]["type"] - MIME-тип прийнятого файлу (якщо браузер зміг його визначити), наприклад: image/gif, image/png, image/jpeg, text/html;
  • (Так ми назвали поле завантаження файлу) - містить ім'я файлу в тимчасовому каталозі, наприклад: /tmp/phpV3b3qY;
  • $_FILES["uploadfile"]["error"] - Код помилки, яка може виникнути під час завантаження файлу. Ключ ["error"]був доданий до PHP 4.2.0. З відповідними кодами помилок ви можете ознайомитись

Після завершення роботи скрипта, тимчасовий файл буде видалено. Це означає, що ми повинні скопіювати його в інше місце до завершення роботи скрипта. Тобто алгоритм роботи сценарію завантаження файлу на сервер такий:

Якщо кнопка "Submit" натиснута, файл вже буде завантажений на сервер і його ім'я будуть в змінній $_FILES["uploadfile"]["name"] . У цьому випадку скрипт повинен відразу скопіювати файл з ім'ям $_FILES["uploadfile"]["tmp_name"] у якийсь каталог (потрібні права на запис до цього каталогу).

Копіювання файлу виконується функцією copy() :

Використовуйте лише функцію копіювання copy() , а не переміщення, оскільки:

  • Тимчасовий файл буде видалено автоматично;
  • Якщо тимчасовий каталог знаходиться на іншому носії, буде виведено повідомлення про помилку.

Припустимо, нам потрібно завантажити файл у каталог uploads, який знаходиться в кореневому каталозі веб-сервера (у каталозі DocumentRoot).

// Про всяк випадок створимо каталог. Якщо його вже створено,
// Повідомлення про помилку ми не побачимо, оскільки скористаємося оператором @:

@mkdir("uploads", 0777);

// Копіюємо файл з /tmp в uploads
// Ім'я файлу буде таким самим, як і до відправки на сервер:

Copy($_FILES["uploadfile"]["tmp_name"],"uploads/".basename($_FILES["uploadfile"]["name"])));

У Linux все набагато складніше - нам потрібно враховувати права доступу до каталогу uploads. Швидше за все в такому випадку, функція mkdir() не спрацює, тому що ми не маємо прав на запис у каталог DocumentRoot (зазвичай це /var/www/html або /home/httpd/html). Зареєструйтесь у системі як користувач root , створіть каталог uploads та змініть його власника та права доступу таким чином:

// Створюємо каталог uploads

// Встановлюємо ім'я власника apache та його групу - теж apache:

Chown apache:apache uploads

// Роздільна здатність запису всім (777) + установка закріплюючого біта (1):

Chmod 1777 завантаження

Розмір файлу можна обмежити, за бажання можна відредагувати файл .htaccess і обмежити доступ до каталогу uploads - вказати або конкретних користувачів, яким можна звертатися до каталогу, або IP-адреси.

Ось тепер можна завантажувати файли на сервер.

Пишемо PHP скрипт завантаження файлів на сервер

Завантаження кількох файлів можна реалізувати, використовуючи, наприклад, різні значення 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"] матиме значення some.html , а змінна $_FILES["userfile"]["name"] - значення file.bin . Аналогічно, змінна $_FILES["userfile"]["size"] міститиме розмір файлу some.html і так далі.

Змінні $_FILES["userfile"]["name"] , $_FILES["userfile"]["tmp_name"] , $_FILES["userfile"]["size"] та $_FILES["userfile"]["type "] також будуть ініціалізовані.

Висновок:

Як бачите, організувати завантаження файлів на сервер не так складно. Складніше забезпечити необхідний рівень безпеки, оскільки завантаження файлів на сервер можна використовувати зловмисниками для атаки на сервер. Про те, як забезпечити необхідний рівень безпеки, працюючи з Uploads дивіться .



>
Є ще питання чи щось незрозуміло - ласкаво просимо на наш

У цій нотатці хочу висвітлити цікавий спосіб завантаження файлів на сервер. Срипт, який вийде повністю робочий і після деякої адаптації може бути використаний вами, у ваших проектах, якщо, звичайно, буде вам цікавий.

Так цей спосіб можна назвати "AJAX завантаження файлів на сервер", хоча він і не використовує ні ActiveXObject ні XMLHttpRequest, проте це те, що згодом перетворилося на AJAX. Взагалі, тут я розкрию кілька трюків розробки, які будуть досить гарною знахідкою для початківців.

У перших метод використовує поля, що динамічно додаються / видаляються завантаження файлів (листинг JavaScript додається) - тобто. у цій нотатці розглядається завантаження та обробка невизначеної множини файлів на сервер, і як завжди я намагаюся писати якомога лаконічніше і зрозуміліше.

По друге, звичайно все відбуватиметься, саме без перезавантаження сторінки.

По-третє, буде дано серверний скрипт, який приймає дані, виводить інформацію, та обробляє помилки завантаження файлів.

І в четвертих, наприкінці завантаження файлів, користувачеві буде виведено інформацію про те, які файли завантажилися, а які ні, і чому. Загалом, цінна штука в арсеналі розробника.

Як ми вже знаємо, при написанні html форм атрибути "name" - елементів форми, згодом є ключами глобальних масивів: $_REQUEST $_GET або $_POST і якщо у формі будуть два поля з однаковим атрибутом "name", то значення останнього поля "затре" значення попередніх у глобальному масиві. Тобто. якщо у нас є таке:

То в обробному скрипті ма побачимо масив $_FILES, яким буде лише один ключ "upfile", а значення першого поля з id="one" - затреться.

Вирішується така проблема просто: даємо різні імена атрибутам "name" і "id". Але! Що робити, якщо поля для завантаження файлів повинні додаватися динамічно, і їхня кількість заздалегідь невідома? Як правило, програмісти вважають за краще генерувати подібні речі в циклі, додаючи до атрибуту "name" якийсь числовий суфікс, домагаючись тим самим унікальності атрибуту "name", а атрибут id за рідкісним винятком майже завжди можна опустити (Згадуємо методи DOM для доступу до елементів) Серверний скрипт генерації форми може мати такий вигляд:



Подібні публікації