Як відправити файл на сервер
В ході розробки одного з проектів постало завдання відправляти з сайту "A" на сайт "B" архів з файлами, який в подальшому треба розкрити на сайті "B". Причому файл повинен динамічно генеруватися на сайті "A". і відправлятися в автономному режимі з PHP-скрипта без участі всіляких форм і т.д.
Я вирішив цю задачу двома методами, і хочу поділитися ними з вами.
Метод №1: відправка файлу методом POST
Ідея полягає в тому, що на сайті "A" формується POST-запит, який в собі містить назву і вміст файлу, який потрібно передати, і посилається на сайт "B". На сайті "B" POST-запит приймається, і в зазначений файл пишеться вказане вміст.
Технологію передачі POST-запиту з PHP-скрипта я поклав на сокети.
Для того, щоб передати дані методом POST, потрібно сформувати рядок, що містить заголовки запиту і безпосередньо самі дані.
Зразковий вид рядки, що відсилається на сервер, може бути таким:
Як ви бачите, змінні в POST-запиті задаються як при GET-запиті, тобто var1 = val1var2 = val2
Далі відкриваємо сокет за допомогою функції fsockopen (). де в параметрах передаємо ім'я домену, якому передаємо запит, номер порту, змінну, що містить номер помилки передачі (якщо така буде), змінну, що містить опис помилки (якщо така буде), і час закриття сокета при просте (в секундах):
Віддаємо дані у відкритий сокет і читаємо відповідь сервера "B".
В результаті роботи скрипта з сайту "A" йде POST-запит на сайт "B". а саме в скрипт import.php. що знаходиться в корені сайту "B". Тобто запускається скрипт import.php. де в сценарії буде доступний масив $ _POST. що містить змінні filename і content.
Все, що нам потрібно, так це відкрити на запис файл з ім'ям $ _POST [ 'filename']. і записати туди дані з змінної $ _POST [ 'content'].
Усе! Файл прийнятий і збережений!
Але є одне АЛЕ: переданий файл може бути будь-якого типу. І бінарний і текстової. Як ви бачили, вміст файлу передається в POST-запиті у вигляді var1 = val1var2 = val2. тобто якщо <здесь содержимое файла file.zip> буде бінарним, або містити URL-значущі символи, то цілісність переданого файлу може бути порушена, або файл не буде переданий взагалі!
Щоб цього уникнути, вміст файлу перед відправкою необхідно перетворити до URL-неактивного виду. Зробити це можна за допомогою функції base64_encode ().
і вже змінну $ file_content вставляти в POST-запит:
У цьому випадку вміст файлу буде передано в "безпечному" вигляді.
Прийом і "дешифрацию" вмісту файлу на сайті "B" можна здійснити за допомогою функції base64_decode ().
Варто зазначити, що даний спосіб прекрасно працює для відносно невеликих файлів (приблизно до 2-х мегабайт, для отримання більш точного значення необхідно дивитися в настройках PHP максимальний обсяг прийнятих даних методом POST).
Якраз у зв'язку обмеженням за розміром переданого файлу, пропоную наступний метод передачі файлів.
Метод №2: відправка файлу методом PUT
Як вже говорилося, відправка файлів на віддалений сервер методом POST через сокети хороша для файлів малих розмірів. Для передачі файлів великих розмірів необхідно застосувати передачу методом PUT.
Для цього скористаємося бібліотекою curl.
Для передачі файлу методом PUT нам необхідно ініціалізувати сеанс CURL, задати для сеансу необхідні параметри, виконати запит CURL і закрити сеанс.
Наступний приклад демонструє передачу файлу file.zip сервера "B".
Після виконання цього сценарію з сайту "A" на сайт "B" піде PUT-запит, в якому буде знаходиться вміст переданого файлу, а в GET-запиті буде міститися назва переданого файлу.
Далі нам необхідно організувати прийом файлу на сайті "B".
Для цього в скрипті import.php. що знаходиться на сайті "B". з масиву $ _GET ми повинні отримати назву файлу, а з вхідного потоку - вміст файлу:
Таким методом можна передавати файли великих обсягів.
Варто напевно також згадати, що наведені вище два способи передачі файлів не є єдино можливими способами. Наприклад, можна передавати файли з PHP-скриптів на віддалені сервера по FTP-протоколу (використовуючи той же CURL або спеціальні функції PHP, такі як ftp_connect (), ftp_login (), ftp_put () і т.д.). Але ж доступ до сайту по FTP може бути утруднений (не відомі ім'я користувача і пароль, або вони були змінені на сервері але не змінені в скриптах і т.д.). А вказаний тут спосіб буде коректно працювати на будь-яких типах хостингу (виключаючи хіба що деякі безкоштовні хостинги, де заборонений прийом даних з інших сайтів).