В этом руководстве наша цель — создать класс FTP с PHP, который будет хорошо написан, полезен и расширяем.
Излагая нашу цель
Всегда важно сначала определить, какие именно функции должен включать ваш класс. В нашем случае:
- подключение к серверу
- создать папку на сервере
- загрузить файл
- изменить каталог
- получение списка каталогов
- скачать файл
Когда я буду использовать класс FTP?
Есть несколько случаев, когда можно использовать этот класс. Пара сценариев может быть:
- Автоматизируйте загрузку изображений, таких как галерея, на веб-сайт клиента (в идеале, в сочетании с моим изменением размера изображения)
- Выполните резервное копирование вне сайта, передав файл резервной копии базы данных с вашего сервера на другой. ( Примечание: это не рекомендуется для конфиденциальной информации, так как FTP не очень безопасный протокол. )
Примечание. Проблемы с FTP легко возникают из-за различных конфигураций сервера. Этот код был успешно протестирован на нескольких FTP-серверах.
Что такое FTP?
FTP: «Стандартный сетевой протокол, используемый для копирования файла с одного хоста на другой».
FTP, или протокол передачи файлов, как определено в Википедии: «Стандартный сетевой протокол, используемый для копирования файла с одного хоста на другой по сети на основе TCP / IP, такой как Интернет».
По сути, это позволяет копировать файлы с одного компьютера на другой.
Шаг 1 — Подготовка
Мы начнем как можно проще. В корне вашего нового проекта создайте два файла: index.php
и ftp_class.php
.
Файл index.php
— это наша главная страница, которая создает объект и вызывает необходимые методы. ftp_class.php
— это просто наш класс ftp.
На следующем шаге мы собираемся создать каркас для нашего класса. Как только это будет сделано, вы сможете следовать и пробовать каждый шаг.
Шаг 2 — Настройка класса
Сила объектно-ориентированного программирования (ООП) состоит в том, чтобы предоставить сложный код простой в использовании интерфейс. Создавая класс — думайте о классе как о шаблоне — вы можете инкапсулировать данные, что является просто жаргоном для термина, который относится к сокрытию данных. Затем мы можем многократно использовать этот класс без необходимости переписывать какой-либо код. Вместо этого вам нужно только вызвать соответствующие методы (термин « method
» такой же, как и function
).
Давайте начнем создавать наш класс ftp. Откройте файл ftp_class.php
и добавьте следующий код. Это базовая структура скелета класса, которую я назвал « FTPClient
».
Функция construct
, известная как конструктор, представляет собой специальный метод класса, который автоматически вызывается классом при создании нового объекта или экземпляра класса. Обычно это хорошее место для добавления инициализации; но для сегодняшних целей нам это не нужно. Тем не менее, мы будем держать его здесь для будущего использования.
1
2
3
4
5
6
|
Class FTPClient
{
// *** Class variables
public function __construct() { }
}
|
Обратите внимание, что мы используем двойное подчеркивание для этого метода construct
.
Шаг 3 — Переменные класса
Далее мы установим некоторые переменные класса или свойства.
1
2
3
|
private $connectionId;
private $loginOk = false;
private $messageArray = array();
|
private
префикс определяет область действия переменной. В этом случае это означает, что переменная не может быть доступна из-за пределов класса.
Переменная $connectionId
будет хранить наш поток соединения. Два других хранят статус и любые сообщения. $loginOk
будет полезен при определении, правильно ли мы подключены.
Шаг 4 — Простая регистрация сообщений
Почти в каждом методе мы будем вызывать метод с именем ‘ logMessage
. Это очень простой обработчик сообщений, который позволит нам захватывать любые сообщения, созданные нашим классом, чтобы мы могли предоставить пользователю обратную связь.
Обратите внимание, что мы не
return
реальные сообщения из наших методов. Вместо этого мы возвращаемtrue
илиfalse
, основываясь на том, была ли конкретная операция успешной. Это имеет свои преимущества, но также не детализирует пользователю, что происходит.
Добавьте следующие два метода, чтобы мы могли определить, что будет успешным.
Этот метод принимает переменную $message
. Содержимое этой переменной затем сохраняется в нашем массиве классов благодаря строке: $this->messageArray[] = $message;
1
2
3
4
|
private function logMessage($message)
{
$this->messageArray[] = $message;
}
|
Поскольку $messageArray
является переменной класса, мы можем получить к ней доступ через нотацию $this->
.
Внутри класса
$this
относится к самому объекту.
Чтобы получить сообщение, мы вызываем getMessages
.
1
2
3
4
|
public function getMessages()
{
return $this->messageArray;
}
|
Этот метод является публичным методом. Как упоминалось ранее, этот частный / публичный бизнес просто относится к области действия переменной или, в данном случае, к методу. Закрытый метод (или переменная) не может быть доступен вне класса, в то время как открытый метод (или переменная) может.
Поскольку наша переменная является частной, нам нужен способ доступа к ней. Мы делаем это, предоставляя нашему классу public
метод, к которому мы можем затем обращаться за пределами класса. Вы можете удивиться, почему мы не можем просто сделать messageArray
переменную messageArray
. Мы можем; Тем не менее, это просто не очень хорошая практика.
Примечание. В Интернете есть множество примеров полнофункциональных обработчиков сообщений или посвященных им классов. Мы работаем над простой реализацией для целей этого урока.
Шаг 5 — Подключение
На этом шаге мы добавим метод connect
. Это позволит нам подключиться к FTP-серверу.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public function connect ($server, $ftpUser, $ftpPassword, $isPassive = false)
{
// *** Set up basic connection
$this->connectionId = ftp_connect($server);
// *** Login with username and password
$loginResult = ftp_login($this->connectionId, $ftpUser, $ftpPassword);
// *** Sets passive mode on/off (default off)
ftp_pasv($this->connectionId, $isPassive);
// *** Check connection
if ((!$this->connectionId) || (!$loginResult)) {
$this->logMessage(‘FTP connection has failed!’);
$this->logMessage(‘Attempted to connect to ‘ . $server . ‘ for user ‘ . $ftpUser, true);
return false;
} else {
$this->logMessage(‘Connected to ‘ . $server . ‘, for user ‘ . $ftpUser);
$this->loginOk = true;
return true;
}
}
|
Мы передаем информацию о соединении: сервер ( $server
), имя пользователя ( $ftpUser
) и пароль ( $ftpPassword
), чтобы позволить нам установить соединение.
Первая строка кода открывает FTP-соединение с ftp_connect
к указанному серверу. Мы сохраняем наше соединение с переменной класса $connectionId
описанной выше.
Код ftp_login
регистрирует нас на указанное соединение, передавая connection id
нашего connection id
, наше имя пользователя и пароль.
Вы могли заметить строку кода ftp_pasv
. Это, как следует из комментария, включает / выключает пассивный режим. Я бы посоветовал вам отключить его, однако, если у вас возникнут проблемы с подключением, попробуйте включить его. Пассивный режим может вызвать проблемы с подключением через FTP.
Мы определяем, было ли соединение успешным. Затем мы регистрируем результаты, вызывая наш простой метод обработчика сообщений, logMessage()
, и передаем строку в log. Помните: мы используем $this->
для доступа к logMessage()
, так как это переменная класса.
Шаг 6 — Вызов объекта
Теперь, когда наш класс работает, мы можем проверить это! Откройте файл index.php
и добавьте следующий код.
Вам понадобится доступ к FTP-серверу, чтобы играть вместе. Если вы хотите настроить свой собственный сервер, попробуйте Filezilla — это тоже бесплатно.
Вы заметите, что я добавил детали FTP-сервера здесь. В идеале они будут храниться в вашем config
файле. Измените их в соответствии с настройками вашего FTP-сервера.
После определения деталей нашего FTP-сервера мы включаем класс с помощью include('ftp_class.php');
, Это означает: сделать класс доступным на этой странице. Следующая строка создает объект нашего класса FTP и сохраняет его в переменной $ftpObj
. $ftpObj
теперь будет использоваться для доступа к любым публичным методам в нашем классе. Это делается с помощью нотации ->
, как в следующей строке, вызывая метод $ftpObj -> connect
и передавая ему данные нашего сервера.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
// *** Define your host, username, and password
define(‘FTP_HOST’, ‘192.168.1.88’);
define(‘FTP_USER’, ‘Blimpf’);
define(‘FTP_PASS’, ‘catfish’);
// *** Include the class
include(‘ftp_class.php’);
// *** Create the FTP object
$ftpObj = new FTPClient();
// *** Connect
$ftpObj -> connect(FTP_HOST, FTP_USER, FTP_PASS);
|
Как видите, как только наш класс будет на месте, подключиться к нашему FTP-серверу очень просто!
Шаг 6б — Просмотр вывода
На последнем шаге мы можем заключить вызов connect в оператор if
, как показано ниже. Затем, если мы не сможем подключиться, зависимый код не будет выполнен. Затем мы можем вывести любые сообщения пользователю, такие как «подключено» или «не удалось».
01
02
03
04
05
06
07
08
09
10
|
// *** Connect
if ($ftpObj -> connect(FTP_HOST, FTP_USER, FTP_PASS)) {
// *** Then add FTP code here
echo ‘connected’;
} else {
echo ‘Failed to connect’;
}
|
Это нормально, хотя наш код быстро раздуется с помощью операторов IF / ELSE, если мы добавим это ко всем нашим вызовам. Вместо этого я хотел бы предложить альтернативу, которая сделает вещи немного чище и легче следовать.
Помните методы обработки сообщений, которые мы добавили? Если вы хотите видеть сообщения, созданные классом — полезные для отладки / обратной связи — вы можете добавить следующий код после любого метода, который вы вызываете.
1
|
print_r($ftpObj -> getMessages());
|
Это покажет сообщение класса.
Шаг 7 — Создание нашего первого каталога
Отлично, теперь пришло время сделать что-то полезное. Первый метод, который мы собираемся создать, это метод makeDir
. Как и ожидалось, этот метод создаст для нас каталоги на сервере. Единственный параметр, который мы передадим — это путь к каталогу и имя папки; мы назовем это $directory
. Волшебная линия здесь — встроенная функция ftp_mkdir
. Он использует наш сохраненный « connectionId
» и переданную переменную $directory
для создания папки.
Добавьте следующий код в ваш файл ftp_class.php
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
|
public function makeDir($directory)
{
// *** If creating a directory is successful…
if (ftp_mkdir($this->connectionId, $directory)) {
$this->logMessage(‘Directory «‘ . $directory . ‘» created successfully’);
return true;
} else {
// *** …Else, FAIL.
$this->logMessage(‘Failed creating directory «‘ . $directory . ‘»‘);
return false;
}
}
|
И, чтобы вызвать его из вашего файла index.php
, добавьте:
1
2
3
4
|
$dir = ‘photos’;
// *** Make directory
$ftpObj->makeDir($dir);
|
Переменная $dir
установлена на имя папки, которую мы хотим создать на сервере. В данном случае: «фото».
Следующая строка вызывает метод, который создаст папку.
Если вы получили сообщение об ошибке «Отказано в доступе», убедитесь, что вы можете написать в указанной папке. Вам может потребоваться создать папку в каталоге, например
/httpdocs
.
Шаг 8 — Загрузка файла
Продолжая, давайте zoe.jpg
фотографию, которая называется zoe.jpg
. При загрузке файла нам нужно указать, какой тип файла мы загружаем — binary
или ascii
? По сути, если вы загружаете текстовый файл, мы должны использовать ascii
; в противном случае он должен быть установлен в двоичный файл.
Мы начнем с настройки array
со всеми расширениями, которые мы должны использовать для загрузки типа ascii
.
1
|
$asciiArray = array(‘txt’, ‘csv’);
|
Затем мы получаем расширение нашего файла, чтобы мы могли проверить, является ли он одним из типов ascii
. Мы определяем это, получая расширение загружаемого файла. Быстрый и грязный метод, который я использовал здесь,
» взорвав » файл с помощью ‘ .
‘как разделитель. Это разделит файл на части и сохранит их в виде array
. Используя другую встроенную PHP-функцию « end », мы выбираем последний элемент array
который содержит наше расширение. Это немного кода.
1
|
$extension = end(explode(‘.’, $fileFrom));
|
Затем мы проверяем, присутствует ли наше расширение в списке (с in_array ) расширений файлов, которые должны быть загружены как тип ascii
. Если он появляется в списке, мы устанавливаем переменную $mode
в FTP_ASCII
; в противном случае мы предполагаем, что это двоичный тип, и присваиваем $mode
значение FTP_BINARY
.
1
|
in_array($extension, $asciiArray)
|
ftp_put
загружает файл из вашего локального местоположения в удаленный файл на FTP-сервере. Мы передаем ему наш « connectionId
», путь к файлу, в который мы хотим загрузить ( $fileTo
), путь
файла, который мы хотим загрузить ( $fileFrom
), и режим ( $mode
), который мы только что определили.
Затем добавьте следующий метод в ваш файл ftp_class.php
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public function uploadFile ($fileFrom, $fileTo)
{
// *** Set the transfer mode
$asciiArray = array(‘txt’, ‘csv’);
$extension = end(explode(‘.’, $fileFrom));
if (in_array($extension, $asciiArray)) {
$mode = FTP_ASCII;
} else {
$mode = FTP_BINARY;
}
// *** Upload the file
$upload = ftp_put($this->connectionId, $fileTo, $fileFrom, $mode);
// *** Check upload status
if (!$upload) {
$this->logMessage(‘FTP upload has failed!’);
return false;
} else {
$this->logMessage(‘Uploaded «‘ . $fileFrom . ‘» as «‘ . $fileTo);
return true;
}
}
|
Конечно, вы можете создать или загрузить любое имя папки по вашему желанию! Добавьте следующий фрагмент кода в файл index.php
и внесите соответствующие изменения.
1
2
3
4
5
|
$fileFrom = ‘zoe.jpg’;
$fileTo = $dir .
// *** Upload local file to new directory on server
$ftpObj -> uploadFile($fileFrom, $fileTo);
|
К настоящему времени вы должны прийти к соглашению с тем, насколько просто использовать этот класс! Мы просто делаем отдельные вызовы для выполнения наших задач — все благодаря объектно-ориентированному программированию!
Шаг 9 — Просмотр файлов
Теперь давайте подтвердим, что наш файл находится в папке с photo
. Мы можем сделать это, перейдя в папку « photo
» на нашем сервере, а затем отобразить содержимое.
Метод changeDir
использует « ftp_chdir
» для изменения текущего каталога на ftp-сервере. Просто перейдите в каталог, чтобы перейти к. Просто и мило.
ftp_class.php:
01
02
03
04
05
06
07
08
09
10
|
public function changeDir($directory)
{
if (ftp_chdir($this->connectionId, $directory)) {
$this->logMessage(‘Current directory is now: ‘ . ftp_pwd($this->connectionId));
return true;
} else {
$this->logMessage(‘Couldn\’t change directory’);
return false;
}
}
|
getDirListing
отобразит содержимое каталога, в котором вы находитесь, используя функцию » ftp_nlist
«. Эта функция возвращает список файлов в данном каталоге. Текущий каталог установлен по умолчанию, поэтому вам не нужно указывать какие-либо параметры.
Если вы хотите, вы можете переопределить это, передав путь к $directory
вы хотите просмотреть содержимое. Переменная $parameters
умолчанию -la
. Это команда Linux для отображения дополнительной информации о каталоге. Не стесняйтесь удалить его или передать пустую строку.
ftp_class.php:
1
2
3
4
5
6
7
|
public function getDirListing($directory = ‘.’, $parameters = ‘-la’)
{
// get contents of the current directory
$contentsArray = ftp_nlist($this->connectionId, $parameters . ‘ ‘ . $directory);
return $contentsArray;
}
|
Метод getDirListing
возвращает array
который содержит наш список каталогов.
index.php
01
02
03
04
05
06
07
08
09
10
|
// *** Change to folder
$ftpObj->changeDir($dir);
// *** Get folder contents
$contentsArray = $ftpObj->getDirListing();
// *** Output our array of folder contents
echo ‘<pre>’;
print_r($contentsArray);
echo ‘
|
«;
Ваш результат должен выглядеть так:
Шаг 10 — Загрузка файла
По мере продвижения к завершению этого урока мы переходим к загрузке файла. Метод начинается с того же кода, что и uploadFile
, в том uploadFile
, что он определяет, является ли файл, который мы хотим загрузить, ascii
или binary
.
Для этого метода вы просто передаете имя файла (и, возможно, путь, в зависимости от того, находитесь ли вы в той же папке, что и файл, который вы хотите загрузить) файла для загрузки, и имя, которое вы хотите, чтобы этот файл имел на ваш клиентский компьютер.
Чтобы скачать файл, вам нужно вызвать ftp_get
.
1
|
ftp_get($this->connectionId, $fileTo, $fileFrom, $mode, 0)
|
Это загружает файл с удаленного сервера на наш локальный компьютер. Он принимает следующий параметр: наш идентификатор соединения, путь и имя файла для сохранения как локально (будет перезаписан, если он
уже существует) ( $fileTo
), местоположение и имя файла на удаленном сервере ( $fileFrom
) и режим ( $mode
).
ftp_class.php
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
public function downloadFile ($fileFrom, $fileTo)
{
// *** Set the transfer mode
$asciiArray = array(‘txt’, ‘csv’);
$extension = end(explode(‘.’, $fileFrom));
if (in_array($extension, $asciiArray)) {
$mode = FTP_ASCII;
} else {
$mode = FTP_BINARY;
}
// try to download $remote_file and save it to $handle
if (ftp_get($this->connectionId, $fileTo, $fileFrom, $mode, 0)) {
return true;
$this->logMessage(‘ file «‘ . $fileTo . ‘» successfully downloaded’);
} else {
return false;
$this->logMessage(‘There was an error downloading file «‘ . $fileFrom . ‘» to «‘ . $fileTo . ‘»‘);
}
}
|
Мы собираемся загрузить тот же файл, который мы загрузили, сохранив его под другим именем на нашем клиентском компьютере.
Примечание: еще раз, убедитесь, что ваши разрешения установлены правильно!
Поскольку теперь мы должны находиться внутри нашей папки с photo
, мы не добавляем путь к переменной $fileFrom
— только имя файла.
index.php
1
2
3
4
5
|
$fileFrom = ‘zoe.jpg’;
$fileTo = ‘zoe-new.jpg’;
// *** Download file
$ftpObj->downloadFile($fileFrom, $fileTo);
|
Шаг 11 — Завершение
Чтобы завершить наш класс, давайте добавим магический метод класса __deconstruct
. Этот метод закрывает наше соединение, когда ссылка на наш объект больше не существует — возможно, страница была закрыта. В любом случае этот код запускается и соединение закрывается. Это всегда хорошая практика, чтобы включить это, хотя это не совсем необходимо.
1
2
3
4
5
6
|
public function __deconstruct()
{
if ($this->connectionId) {
ftp_close($this->connectionId);
}
}
|
Вывод
Ну, это делает это! Я надеюсь, что теперь вы лучше понимаете, как использовать FTP с PHP. Теперь у вас должны быть необходимые навыки для дальнейшего расширения этого класса для поддержки других распространенных задач, таких как переименование или удаление файлов и папок.
Обязательно сообщите нам, если вы создадите классные PHP FTP-клиенты!