Работа по FTP протоколу на PHP

Содержание

ftp:// — Доступ к URL-адресам по протоколу FTP(s)

ftp:// — ftps:// — Доступ к URL-адресам по протоколу FTP(s)

Описание

Позволяет читать существующие файлы и создавать новые файлы через FTP. Если сервер FTP не поддерживает режим passive mode, соединение будет невозможно.

Вы можете открыть файл либо для чтения, либо для записи, но не одновременно для того и другого. Если файл на сервере FTP уже существует, и вы пытаетесь открыть его для записи, но не указали опцию контекста overwrite, соединение будет невозможно. Если вам необходимо перезаписать существующие файлы на FTP, укажите опцию overwrite в контексте и откройте файл для записи. Кроме того, вы можете использовать FTP расширение.

Если вы установили директиву from в файле php.ini , то это значение будет отправлено как пароль при анонимном подключении к FTP.

Использование

  • ftp://example.com/pub/file.txt
  • ftp://user:password@example.com/pub/file.txt
  • ftps://example.com/pub/file.txt
  • ftps://user:password@example.com/pub/file.txt

Опции

Основная информация

Атрибут PHP 4 PHP 5
Ограничение по allow_url_fopen Да Да
Чтение Да Да
Запись Да (только новые файлы) Да (новые файлы / существующие файлы с опцией overwrite )
Добавление Нет Да
Одновременное чтение и запись Нет Нет
Поддержка stat() Нет Начиная с PHP 5.0.0 доступны только: filesize() , filetype() , file_exists() , is_file() , и is_dir() . Начиная с PHP 5.1.0 доступны: filemtime() .
Поддержка unlink() Нет Да
Поддержка rename() Нет Да
Поддержка mkdir() Нет Да
Поддержка rmdir() Нет Да

Список изменений

Версия Описание
4.3.0 Добавлена поддержка ftps://.

Примечания

FTPS поддерживается только когда включена поддержка расширения OpenSSL.

Если сервер не поддерживает SSL, то соединение переключается обратно на обычный нешифрованный протокол FTP.

Работа по FTP протоколу на PHP

For those who dont want to deal with handling the connection once created, here is a simple class that allows you to call any ftp function as if it were an extended method. It automatically puts the ftp connection into the first argument slot (as all ftp functions require).

This code is php 5.3+

class ftp <
public $conn ;

public function __construct ( $url ) <
$this -> conn = ftp_connect ( $url );
>

public function __call ( $func , $a ) <
if( strstr ( $func , ‘ftp_’ ) !== false && function_exists ( $func )) <
array_unshift ( $a , $this -> conn );
return call_user_func_array ( $func , $a );
>else <
// replace with your own error handler.
die( » $func is not a valid FTP function» );
>
>
>

// Example
$ftp = new ftp ( ‘ftp.example.com’ );
$ftp -> ftp_login ( ‘username’ , ‘password’ );
var_dump ( $ftp -> ftp_nlist ());
?>

Upload file to server via ftp.

= «» ;
$ftp_user_name = «» ;
$ftp_user_pass = «» ;
$file = «» ; //tobe uploaded
$remote_file = «» ;

// set up basic connection
$conn_id = ftp_connect ( $ftp_server );

// login with username and password
$login_result = ftp_login ( $conn_id , $ftp_user_name , $ftp_user_pass );

// upload a file
if ( ftp_put ( $conn_id , $remote_file , $file , FTP_ASCII )) <
echo «successfully uploaded $file \n» ;
exit;
> else <
echo «There was a problem while uploading $file \n» ;
exit;
>
// close the connection
ftp_close ( $conn_id );
?>

In example 2 above you may need to set the system to to use pasv to get a result ie:

$ftp = new ftp(‘ftp.example.com’);
$ftp->ftp_login(‘username’,’password’);
$ftp->ftp_pasv(TRUE);
var_dump($ftp->ftp_nlist());

syntax error in the above example, ftp_nlist requires a directory parameter:

$ftp->ftp_nlist(‘.’); // retrieve contents of current directory

Think about using the ftp:// wrapper for simple manipulations (getting or storing a single file).

Класс для работы с FTP с помощью php. Часть 3

Язык программирования php позволяет легко подключаться к сайту через FTP соединение. Для этого он использует встроенную FTP библиотеку, функции которой чаще всего начинаются с фразы ftp_

В предыдущей части я писал подробно о том, как подключаться по php FTP к удаленному серверу, а также рассказал об основных методах работы с ним. Но лень — двигатель прогресса, поэтому я нашел в сети класс для работы с FTP сильно его изменил — улучшил и добавил новые методы.

Итак класс называется FTPClient, скачать его вы можете по ссыле ниже.

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

На что стоит обратить внимание в классе:

  • private $connectionId; // >private $messageArray = array(); //массив статусов работы с FTP
  • Метод connect — соединение с FTP

Единственное, что я забыл учесть метод закрытия по FTP, чтобы выгрузить ресурсы ( ftp_close($this->connectionId); ) — думаю, вы сами доработаете этот пункт если он вам понадобится, так как соединение по умолчанию открывается на 90 секунд.

Как работать с классом FTP?

На самом деле очень просто — просто создайте экземпляр класса (объект) и используйте следующие доступные методы:

//Создаем объект для работы с FTP
$ftpObj = new FTPClient();
if($ftpObj->connect(‘сервер’, ‘юзер’, ‘пароль_юзера’)) < //соединение успешно установлено - делаем действия
$ftpObj->makeDir(‘/templates/12’); //создаем папку
$ftpObj->delDir(‘/templates/15’); //удаляем папку
$ftpObj->uploadFile(‘/templates/12/indexOLD.php’, $_SERVER[‘DOCUMENT_ROOT’].’/index.php’); //загружаем файл с текущего сервера на удаленный
$ftpObj->downloadFile($_SERVER[‘DOCUMENT_ROOT’].’/indexNEW.php’, ‘/templates/12/index.php’); //скачиваем файл из удаленного сервера в текущий
$ftpObj->delFile(‘/templates/12/img.png’); //удаляем файл
$ftpObj->listFile(‘/templates’); //получаем список файлов и папок директории
>

Во всех этих методах нужно лишь передавать параметры — что создаем/удаляем, куда/откуда загружаем/скачиваем.

При работе с загрузкой, скачкой файлов через FTP — в данном примере файлы начинающиеся с $_SERVER[‘DOCUMENT_ROOT’] относятся к текущему серверу из которого запущен FTP класс.

Чтобы посмотреть логи того, что происходит добавьте в конце код:

for($as_log = 0; $as_log logMessage()); $as_log++) < echo $ftpObj->logMessage()[$as_log].’
‘; >

Он показываем все статусы по работе с FTP. Это бывает очень удобным, чтобы контролировать работу скрипта.

Вот такой вот класс у меня получился. Полюсом ООП в PHP является то, что вы легко сможете его модернизировать для себя, добавить новые методы или улучшить старые!

Работа с FTP средствами PHP

Основные возможности PHP при работе с FTP

Протокол FTP (File Transfer Protocol — протокол передачи файлов) — один из старейших протоколов Интернета, предназначенный для передачи файлов между двумя хостами.

Как правило, при работе с FTP выполняются следующие стандартные действия:

  • соединение с удаленным FTP-сервером
  • регистрация на FTP-сервере
  • загрузка файлов с сервера или на сервер
  • закрытие соединения

Соединение с FTP-сервером

Соединение с удаленным FTP-сервером выполняется с помощью функции ftp_connect:

В качестве обязательного параметра эта функция принимает имя хоста host, с которым необходимо установить соединение. Второй необязательный параметр port указывает на номер порта, через который осуществляется соединение. Если этот параметр не указан, то соединение осуществляется через порт 21, являющийся стандартным FTP-портом. Третий необязательный параметр определяет максимально время выполнения сценария (тайм-аут) и по умолчанию равен 90 секундам.

Соединение с удаленным FTP-сервером

Регистрация на FTP-сервере

После того, как соединение установлено, необходимо зарегистрироваться на сервере с определенным именем и паролем. Сделать это можно при помощи функции ftp_login.

Регистрация на FTP-сервере

Как видно из листинга, функция ftp_login принимает три параметра: дескриптор FTP-соединения, возвращаемый функцией ftp_connect, имя пользователя и пароль.

Замечание: Регистрация на сервере не требуется, если FTP-сервер является анонимным.

Закрытие соединения

По окончании сеанса связи с FTP-сервером, нужно закрыть FTP-соединение с помощью функции ftp_quit, принимающей в качестве единственного параметра дескриптор FTP-соединения:

Загрузка файлов с сервера

Загрузка файлов с сервера осуществляется при помощи функции ftp_get:

Аргумент mode, задающий режим пересылки файлов, должен быть указан как константа FTP_BINARY или FTP_ASCII. Режим FTP_ASCII используется для пересылки файлов, состоящих только из ASCII-символов (т. е. текстовых файлов), а двоичный режим — для пересылки всех остальных файлов.

Вещество и поле не есть что-то отдельное от эфира, также как и человеческое тело не есть что-то отдельное от атомов и молекул его составляющих. Оно и есть эти атомы и молекулы, собранные в определенном порядке. Также и вещество не есть что-то отдельное от элементарных частиц, а оно состоит из них как базовой материи. Также и элементарные частицы состоят из частиц эфира как базовой материи нижнего уровня. Таким образом, всё, что есть во вселенной — это есть эфир. Эфира 100%. Из него состоят элементарные частицы, а из них всё остальное. Подробнее читайте в FAQ по эфирной физике.

FTP-протокол + WinSocks на примере простого FTP-клиента (зеркала) на ASM!

Это еще одна статья «давно гуляющая» по интернету, и опять, как автор, сделаю перепост. Думаю пригодиться и тут.

Введение

В этой статье я не ставлю себе целью пересказать все RFC касающиеся протокола FTP, коих не мало, в них вы сможете найти информацию гораздо полнее, попытаюсь лишь в общих чертах познакомить Вас с протоколом FTP и основными приемами работы с ним со стороны клиента.

Общие сведения о протоколе FTP

Итак, FTP (File Transfer Protocol) – протокол передачи файлов в сетях стандарта TCP/IP. Этот протокол был специально создан для облегчения и стандартизации программирования алгоритмов передачи файлов между клиентом и сервером. Как и все протоколы высокого уровня, он не занимается непосредственной передачей данных (этим занимается протокол более низкого уровня – TCP, а так же протоколы ниже), а лишь описывает способ «общения» клиент-сервер.

Перейдем непосредственно к описанию протокола. Отличительной его особенностью является использование двух соединений между сервером и клиентом. Одно соединение (командное или управляющее) используется для передачи команд серверу, а так же приема ответов на эти команды. Второе соединение (соединение данных) используется непосредственно для приема или передачи данных. Управляющее соединение всегда происходит со стороны клиента на порт сервера 21 и остается на протяжении всего сеанса работы открытым. Соединение данных открывается и закрывается по мере необходимости в приеме или получении данных.

После того как установлено управляющее соединение клиент может отправлять по нему серверу различные команды. Каждая команда представляет из себя 3 или 4 заглавных символа ASCII, за которыми после одного или более пробелов следуют, в некоторых командах не обязательные аргументы. Любая команда заканчивается парой CR, LF – это, несомненно, известные всем 0dh, 0ah – если речь идет о DOS/Windows. В общих чертах схема команды такая:

Команда [аргумент(ы)] CR, LF.

Всего существует чуть более 30 команд (в RFC959 – 33) которые могут быть посланы серверу, но это совсем не значит что сервер все их будет поддерживать. Приведу пример наиболее часто используемых команд.

USER имя пользователя
Указывает имя пользователя

PASS пароль
Указывает пароль пользователя

LIST список файлов
Запрос списка файлов

PORT n1,n2,n3,n4,n5,n6
Указание IP и порта для соединения данных

RETR имя файла
Получить файл с сервера

STOR имя файла
Положить файл на сервер

TYPE тип
Тип передаваемых данных

QUIT
Отключение от сервера

ABOR
Отмена предыдущее команды. Прекращение передачи данных.

При получении запроса сервер, по тому же управляющему соединению отправляет ответ на него. Ответ сервера состоит из трех символов (цифр) в формате ASCII, за которыми следует не обязательный текст, обычно поясняющий цифирный код ответа, за этим пояснением следуют неизменные CR, LF. Ответ например может быть таким: 226 File send OK. – в этом примере сервер сообщает нам о том, что файл отправлен с его стороны (что совсем не означает, что он уже получен со стороны клиента). Первая цифра отклика сервера наиболее значимая, и дает однозначное представление о том как выполнилась (или не выполнилась) команда. Значения могут быть такими:

  • 1хх Команда находится в процессе выполнения, необходимо дождаться еще одного сообщения перед тем, как давать следующую команду.
  • 2хх Команда выполнена. Сервер находится в ожидании следующей.
  • 3хх Команда выполнена, но для продолжения необходима еще одна команда
  • 4хх Команда не была выполнена, необходимо подождать и повторить команду
  • 5хх Команда не была выполнена и не будет выполнена при повторе.

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

  • x0x Ошибка синтаксиса.
  • x1x Информация.
  • x2x Отклик относится к состоянию управляющего или соединению данных.
  • x3x Отклик относится к аутентификации пользователя или состоянию бюджета.
  • x4x Не определенно.
  • x5x Отклик относится к состоянию файловой системы.

Ну и наконец третья цифра отклика несет в себе дополнительную информацию.

Следует обратить особое внимание на то, что хотя на большую часть команд сервер отвечает одним откликом, есть и широко используются команды, в ответ на которые сервер генерирует несколько откликов. При этом первая цифра первого отклика будет «1» — т.е. если взглянуть на таблицы выше, сервер сообщает нам о том, что необходимо подождать еще одного сообщения от него, перед тем, как посылать следующую команду. Примером такой команды может служить команда RETR, когда сервер принимает ее и начинает пересылку данных он отвечает нам что-то вроде: «150 Opening BINARY mode data connection for HIDE.ASM (958 bytes).» — смысл сообщения сводится к «начата передача данных». Затем, когда данные им уже будут отправлены (но опять хочу заострить внимание – не факт, что получены клиентом) он отправит по управляющему соединению еще один отклик – «226 File send OK.» — т.е. «файл отправлен». Вот в этом случае только после получения второго сообщения сервер готов к выполнению следующей команды. Вместо последнего сообщения мы вполне можем получить сообщение с ошибкой начинающееся с «4» — в том случае, если возникнут какие-либо проблемы с передачей файла.

В общих чертах это все, что касается управляющего соединения.

Теперь поговорим о соединении данных. Как уже говорилось выше, соединение данных организуется по мере необходимости, и закрывается каждый раз после передачи или приема данных. Так происходит потому, что режим передачи данных между клиентом и сервером – потоковый, а в таком режиме окончание передачи данных – закрытие соединения. Из вышесказанного мы должны сделать один немаловажный вывод – судить об окончании передачи данных со стороны сервера мы можем по закрытию соединения.

Обычно соединение данных открывается следующим образом:

  • клиент выбирает свободный порт на своем хосте и осуществляет пассивное открытие на него;
  • клиент сообщает серверу по управляющему соединению свой IP-адрес и номер порта, на который сделал пассивное открытие;
  • сервер, получив порт и IP-адрес осуществляет его активное открытие;
  • передаются или принимаются данные;
  • в зависимости от того кто передает, а кто принимает данные осуществляется закрытие порта.

Небольшое отступление: если вы внимательно прочтете второй пункт, может возникнуть вопрос – «А что будет если мы передадим серверу фиктивный адрес и порт?». Ответ неоднозначен, сервер может проверять IP-адрес, но это происходит не всегда, поэтому существуют некоторые интересные «заморочки» с использованием фиктивных адресов.

Что касается порта, выбираемого для соединения данных клиентом. Обычно используется динамически назначаемый ОС порт, — т.е. делается запрос к системе, она дает первый свободный. Если клиент не указывает серверу порт для соединения, оно происходит на порт с которого было проведено управляющее соединение (поступать так не рекомендуется). Сервер всегда осуществляет соединение данных с 20-го порта.

Это все основное, что я хотел рассказать о соединении данных.

Теперь, когда мы знаем для чего и как работают оба соединения, хочу отметить еще один момент (при первом прочтении можно пропустить). Команда LIST возвращает список файлов текущей директории, и возвращает его по соединению данных. Список представляет из себя набор строк ASCII оканчивающихся символами CR, LF. Каждая строка несет в себе информацию об одном из элементов запрашиваемого каталога. Общий шаблон этой строки такой:

Txxxxxxxxx[ ]uk[ ]user[ ]group[ ]size[ ]mm[ ]dd[ ]yytt[ ]name CR, LF

T – тип элемента («d» — каталог, «-» — файл, «l» — ссылка и т.д.);
xxxxxxxxx – атрибуты защиты файла;
user – пользователь, владелец файла;
group – группа владельца;
size — размер элемента;
mm – месяц создания элемента в текстовом виде, например «jul»;
dd – день месяца создания элемента;
yytt – здесь может быть год или время создания элемента;
name – имя элемента (файла, каталога, ссылки);
[ ] – один или более пробелов.

Да, между этими элементами может быть различное количество пробелов, надо сказать спасибо, что в различных реализациях серверов оставили одно количество значимых столбцов, поэтому при анализе таблицы файлов следует это учитывать. Стоит еще учесть такую вещь, что не всегда первая строка из таблицы есть значимая строка, несущая информацию о первом элементе каталога. В некоторых реализациях FTP-серверов (например ftpd на FreeBSD), первой строкой списка является строка «total NN».

Как это должно работать?

Давайте немного отвлечемся и посмотрим, как же должен выглядеть FTP сеанс получения файла «изнутри». Итак, мы запускаем клиента. Сервер в это время уже пассивно открыл и слушает 21-ый порт. В первую очередь нам необходимо создать управляющее соединение – конектимся на сервер на порт 21. Что дальше? Сразу, как только мы удачно законектились с сервером по созданному управляющему соединению нам приходит приветствие от сервера, это будет что-то вроде «220 VSFTP deamon base on Alt Linux 2.2, Shpakovsky».

Следующим шагом должна быть регистрация – допустим мы соединяемся с анонимным сервером — по управляющему соединению клиент посылает серверу команду USER anonymous, на что, если сервер поддерживает анонимного пользователя получаем ответ: «331 Please specify the password.» — «пожалуйста сообщите пароль», заметим цифру «3» в ответе сервера, что означает, что для продолжения требуется еще команда, что собственно и делает клиент – посылаем команду PASS 1@1 – в качестве пароля указав фиктивный e-mail. На что получаем ответ сервера «230 Login successful. Have fun.» — «Регистрация прошла успешно».

Все, теперь наши действия зависят от того что мы хотим, а как говорилось выше, хотим мы получить с сервера файл, пусть к примеру это будет файл «H >
Итак, осталось только получить файл. Для этого клиенту необходимо открыть соединение данных. Клиентом выбирается свободный порт, осуществляется пассивное открытие, т.е. клиент его «слушает». Дальше клиенту нужно сообщить серверу свой IP-адрес и номер порта, который только что пассивно открыл (допусти IP-адрес хоста клиента будет 10.21.23.10, а номер порта 2000). Клиент посылает серверу по управляющему соединению команду PORT 10,21,23,10,7,208 – «что за 7,208?» — спросите вы. Это и есть номер порта строится он так – 7*256+208 = 2000. Сервер после получения этой команды попытается сделать активное открытие указанного порта и в случае удачи вернет что-то вроде «200 PORT command successful. Consider using PASV.».

Все, соединение данных установлено остается дать команду передачи данных серверу, что и делает клиент — RETR HIDE.EXE, на что в случае если все нормально (файл существует и может быть передан) сервер отвечает «150 Opening BINARY mode data connection for HIDE.EXE (4096 bytes).» и начинает сливать файл по соединению данных. Опять обращаю ваше внимание на первую цифру ответа. Когда файл будет полностью отправлен сервер пошлет сообщение «226 File send OK.» и произведет закрытие соединения данных.

Клиент ждет окончания получения данных со своей стороны (о чем свидетельствует получение сообщения от сервера + закрытие соединения данных, тут есть ньюансы, но о них позже) после чего закрывает порт соединения данных со своей стороны.

Итак файл получен клиентом, остается разорвать управляющее соединение, клиент посылает команду QUIT, сервер отвечает «221 Goodbye.» и разрывает соединение.

Вот собственно самое важные теоретические сведения о протоколе. Перед тем как переходить к практике очень советую побаловаться управляющим соединением с FTP-сервером, используя telnet, соединение данных создать не получится, но команды и ответы на них будут на виду. Так же рекомендую поработать с каким-либо консольным клиентом FTP и понаблюдать во время всего этого за созданием и закрытием соединений с помощью какой-нибудь утилиты для этого, коих в Интернете как грязи.

Реализация.

Теперь о самой реализации. В этой реализации клиента я использую non-blocking (не блокирующие) сокеты, поэтому модель клиента – событийная, т.е. выполнять те или иные действия, касающиеся используемых клиентом сокетов клиент будет только при возникновении соответствующего события (например закрытие соединения, уведомление о получении данных и т.д.). В качестве событий используются сообщения, приходящие в процедуру главного окна. Кроме того, модель программы поточная, используется поток для чтения соединения данных и поток для чтения управляющего соединения, а так же основной поток клиента, запускающийся при нажатии на кнопку «соединение». Так как программа многопоточная для синхронизации работы этих трех потоков (а так же процедуры сообщений главного окна) используются «event’s» («события», не путать эти события, используемые программой как датчик 1 или 0 – произошло или не произошло событие, и события касающиеся сокетов, которые приходят на процедуру главного окна).

Итак, начнем. При создании основного окна приложения мы проводим основную инициализацию программы, поясню основные моменты:

call VirtualAlloc,ebx,1024000,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE
mov ReciveDataBufferOffset,eax
call VirtualAlloc,ebx,10240,MEM_COMMIT+MEM_RESERVE,PAGE_READWRITE
mov ReciveCommandBufferOffset,eax
Здесь выделяется память под буфер приема файла (1 Мб) и под буфер команд (10 Кб).

call CreateEventA,ebx,ebx,ebx,ebx
mov HDataReciveEvent,eax
……
Создаются объекты event (события) более подробно о назначении событий позже.

call CreateThread,ebx,ebx,offset ReciveThread,offset ReciveDataThreadStruc, \
NORMAL_PRIORITY_CLASS,offset ThreadID_data
call CreateThread,ebx,ebx,offset ReciveThread,offset ReciveCommandThreadStruc,\
NORMAL_PRIORITY_CLASS,offset ThreadID_command
Создаются 2 потока – один для чтения данных, другой для чтения управляющего потока. Оба этих потока при старте находятся в приостановленном состоянии, и начинают работать только при установлении соответствующего события.

call gethostname, offset HostName,64
call gethostbyname,offset HostName
…..
mov PortInPort,esi
ret 0

Смысл строк выше в получении IP-адреса нашего хоста, небольшом преобразовании и записи его в отдельное место, адрес хоста нам потребуется для выполнения команды PORT.

На этом процесс начальной инициализации заканчивается, и программа находится в состоянии ожидания команды пользователя. Давайте посмотрим что происходит при нажатии пользователем кнопки «соединиться».

В основной процедуре окна создается главный поток приложения, рассмотрим его ключевые моменты.

Сразу при старте мы инициализируем переменные относящиеся к приему данных и получаем из окна диалога введенные пользователям параметры соединения (сервер, пароль и.д.). После этого нам необходимо создать управляющее соединение с сервером, что мы и делаем:

— создаем сокет;
call socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
mov ReciveCommandSock,eax
— выбираем неблокирующий режим для сокета, указываем что хотим получать
сообщения о получении новых данных на сокет, а так же о успешном его
приконекчивании.
call WSAAsyncSelect, ReciveCommandSock, newhwnd, WM_COMMANDSOCK,FD_READ+FD_CONNECT
— получаем информацию об удаленном хосте и конектимся к нему
…..
call connect,ReciveCommandSock,offset sockaddr_in,16
— ждем получения события FD_CONNECT, когда оно приходит в процедуру главного окна
обработчик с помощью call SetEvent,HWaitConnectEvent устанавливает событие,
чего мы и ожидаем в следующей строке, если событие не будет установлено в течении
5 секунд, выводим сообщение об ошибке и заканчиваем сеанс связи.
call WaitForSingleObject,HWaitConnectEvent,5000
call ResetEvent,HWaitConnectEvent
— так как после соединения сервер должен послать нам приветствие, ждем его еще 5
секунд, если оно не поступило — выходим. Процедура WaitAnswerRecive описана ниже.
call WaitAnswerRecive,5000
or eax,eax
jnz errorwithregisration

— входным параметром к функции является интервал, в течении которого, функция будет
ждать ответа сервера, если за указанный интервал ответ не будет получен, функция
выводит сообщение об ошибке и завершается с ненулевым значением регистра eax.

WaitAnswerRecive proc TimeToWait:dword
call WaitForSingleObject,HWaitCommandEvent,TimeToWait
— ожидаем возникновение события HWaitCommandEvent, которое устанавливается в потоке
получения данных по управляющему соединению, в случае успешного получения данных.
or eax,eax
jz NoTimeOutGet
call MessageBoxA,newhwnd,offset ErrTimeOutCommand,offset ErrorCap,40h
call ResetEvent,HWaitCommandEvent
— сбросили событие HWaitCommandEvent т.к. истек таймаут, и событие осталось в
сигнальном состоянии.
NoTimeOutGet:
ret
WaitAnswerRecive endp

Теперь пришло время рассмотреть потоки получения данных, как говорилось выше эти потоки создаются в процессе инициализации главного окна, и находятся постоянно в процессе ожидания новых данных, потоки активизируются в процедуре главного окна при получении ей сообщении о том, что есть новые данные, сообщение для управляющего соединения мы определили в самом начале главного потока функцией WSAAsyncSelect, сообщение для соединения данных определяется при создании этого соединения, как мы увидим позже.

Универсальный трэд для получения данных по управляющему и соединению данных приведен ниже.

— в качестве параметра поток получает адрес структуры ReciveDataThreadStruc
или ReciveCommandThreadStruc в зависимости от предназначения трэда.
Структура для ReciveCommandThreadStruc такая:
— хэндл события по которому трэд активизируется;
HCommandReciveEvent dd ?
— хэндл события, которое устанавливает трэд если все данные успешно получены;
HWaitCommandEvent dd ?
— адрес буфера получения данных;
ReciveCommandBufferOffset dd ?
— здесь содержится общее количество полученных данных;
BytesCommandRecived dd 0
— и наконец, с какого сокета надо получить данные;
ReciveCommandSock dd ?

ReciveThread proc parametr:dword
mov edi,parametr
InfinityLoop:
— ждем возникновения события, что данные можно принимать;
call WaitForSingleObject,dword ptr [edi],-1
— настраиваем esi на место, куда данные будут считаны — адрес буфера+количество
полученных ранее;
mov esi,[edi+8]
add esi,[edi+12]
— получаем не более 4096 байт;
call recv,dword ptr [edi+16],esi,4096,0
— прибавляем к уже полученным ранее, полученные в данный момент;
add [edi+12],eax
— в ebx заносим хэндл события, которое надо установить, если получены все нужные данные;
mov ebx,[edi+4]
— если мы получаем данные по соединению данных то идем к проверке конца получения
данных по соединению данных, иначе — проверяем получили ли мы все данные по
управляющему соединению;
cmp edi,offset ReciveDataThreadStruc
je comparefordata
— по управляющему соединению получены все данные в случае если последние байты ответа
0dh, 0ah, что мы и проверяем;
mov eax,[edi+12]
mov esi,[edi+8]
cmp byte ptr [esi+eax-1],10
je short CallEvent
jmp InfinityLoop
comparefordata:
— по соединению данных получено все, если количество полученных байт = длине файла;
mov eax,[edi+12]
cmp FileLenght,eax
jne InfinityLoop
CallEvent:
— в случае если все данные получены выставляем соответствующее событие;
call SetEvent,ebx
jmp InfinityLoop
ReciveThread endp

Вернемся теперь к основному потоку, мы успешно получили ответ от сервера, в том что он готов к приему команд, теперь мы можем передавать ему команды, в данной реализации за отправку команд серверу отвечает функция SendCommandInSocket, в основном потоке далее мы вызываем эту функцию для отправки серверу последовательно команд: USER, PASS, TYPE, CWD, PORT и LIST. Сама функция выглядит так:

— принимает аргументами сокет, в который нужно передать команду, и смещение на буфер,
в котором содержится команда;
SendCommandInSocket proc uses ebx ecx esi edi, hSocket:dword, OutBufOffset:dword
— сначала определяем длину команды;
mov edi,OutBufOffset
push edi
mov eax,0ah
mov ecx,100
repne scasb
sub edi,OutBufOffset
mov ecx,edi
pop esi
push edi
— переносим команду в буфер для приема ответов для сервера, сделано это для того,
что бы потом его можно было сохранить в удобочитаемом виде лога;
mov edi,ReciveCommandBufferOffset
add edi,BytesCommandRecived
rep movsb
pop edi
add BytesCommandRecived,edi
— посылаем команду в сокет;
call send,hSocket,OutBufOffset,edi,ebx
— ждем ответа сервера, с помощью уже описанной выше функции WaitAnswerRecive;
mov eax,5001
Wait2Answer:
dec eax
push eax
call WaitAnswerRecive
or eax,eax
jnz ErrorProcessed
— ответ получен, ищем первый байт ответа, мы его ИЩЕМ, а не просто используем
смещение на конец предпоследнего полученого сообщения, потому, что нами может
быть получено в одном сеансе получения данных обновременно два ответа от сервера.
Уясните себе этот момент.
mov edi,ReciveCommandBufferOffset
mov ecx,BytesCommandRecived
dec ecx
dec ecx
add edi,ecx
mov al,0ah
std
repne scasb
cld
xor eax,eax
— проверяем первый символ ответа;
mov cl,[edi+2]
cmp cl,’1′
— если это «1» то ждем еще одного сообщения от сервера
jz Wait2Answer
cmp cl,’3′
— если ответ больше «3» — произошла ошибка;
jna NoErrorProcessed
call MessageBoxA,newhwnd,edi,offset ErrorCap,40h
ErrorProcessed:
xor eax,eax
inc eax
NoErrorProcessed:
ret
SendCommandInSocket endp

Необходимо учесть еще одну вещь – перед отправкой команды PORT, нам надо создать слушающий сокет, это мы делаем с помощью вызова процедуры CreateListenSock.

CreateListenSock proc
pushad
— создаем сокет;
call socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
mov datasock,eax
— переводим его в не-блокирующий режим, указывая, что хотим получать в процедуре
окна сообщения о подтверждении приконекчивания к этому сокету, о поступлении
новых данных, и о закрытии соединения;
call WSAAsyncSelect, datasock, newhwnd, WM_DATASOCK, FD_ACCEPT+FD_READ+FD_CLOSE
— ввязываем сокет с локальным адресом;
mov sin_port,0 ; указываем ноль, в этом случае система даст нам
; первый свободный порт
mov sin_family,AF_INET
mov sin_addr,INADDR_ANY
call bind, datasock, offset sockaddr_in, 16
— получаем инфу о сокете;
call getsockname,datasock,offset sockaddr_in,offset szSockaddr_in
— преобразуем номер порта к нормальному виду;
xor eax,eax
mov ax,sin_port
call ntohs,eax
push eax
shr eax,8
— дальше преобразуем номер порта в символы ASCII;
call DECtoASCII,eax,PortInPort
— и записываем их в шаблон команды PORT
mov al,’,’
stosb
pop eax
and eax,0ffh
call DECtoASCII,eax,edi
mov ax,0a0dh
stosw
mov esi,PortInPort
— слушаем сокет;
call listen, datasock, 1
popad
ret
CreateListenSock endp

Итак последней отправленной командой была команда LIST, после нее на соединение данных должен прийти список файлов текущей директории, соответственно после отправки сообщения нам необходимо подождать пока этот список будет нами получен, т.к. даже если сервер отправил нам сообщение о том, что он успешно завершил отправку всех данных это совсем не значит, что наш поток уже все отработал и получил, поэтому мы ожидаем окончания получения функцией WaitTransferComplete.

— получает в качестве аргумента в течении которого мы буде ждать ОКОНЧАНИЯ получения
данных, после того, как соединение будет закрыто со стороны сервера.
WaitTransferComplete proc uses ecx edi, TimeToWaitEndTransfer:dword
WaitProgress:
— ждем установления события закрытия соединения со стороны сервера, оно устанавливается
в главной процедуре окна;
call WaitForSingleObject,HWaitCloseEvent,-1
— дальше ждем, события успешного получения данных нашим потоком, которое в нем и
устанавливается;
call WaitForSingleObject,HWaitDataEvent,TimeToWaitEndTransfer
or eax,eax
jz CloseDataSocks
— был таймаут, и если мы получаем директорию, то выходим без ошибки, т.к. при получении
директории у нас всегда таймаут, потому, что мы заранее не знаем количество получаемых
байт и поток получения не может установить событие успешного получения;
cmp TimeToWaitEndTransfer,1000 ;если ждем каталог
jz CloseDataSocks
call MessageBoxA,newhwnd,offset ErrTimeOutCommand,offset ErrorCap,40h

CloseDataSocks:
— сбрасываем событие успешного получения;
call ResetEvent,HWaitDataEvent
— закрываем соединение со своей стороны;
call closesocket,ReciveDataSock
call closesocket,datasock
ret
WaitTransferComplete endp

В случае успешного завершения процедуры выше в буфере приема данных будет лежать таблица каталога. Ниже по программе мы обрабатываем полученную таблицу и по очереди получаем все найденные в ней файлы, получение файла ничем не отличается от получения директории, поэтому здесь этого я описывать не буду. После того, как все файлы были получены и сохранены мы закрываем управляющее соединение и завершаем поток.

Заключение.

Мы разобрали основные принципы работы с протоколом FTP со стороны клиента, конечно же были затронуты далеко не все аспекты этой задачи. Например не была рассмотрена отправка файлов на сервер, но думаю, внимательно изучив материал выше, а так же прилагающийся исходный код, можно без проблем сделать и это, пусть дальнейшее изучение протокола FTP со стороны сервера будет вашим «домашним заданием».

Как работать с PHP и FTP

В этом руководстве наша цель — создать класс 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 , известная как конструктор, представляет собой специальный метод класса, который автоматически вызывается классом при создании нового объекта или экземпляра класса. Обычно это хорошее место для добавления инициализации; но для сегодняшних целей нам это не нужно. Тем не менее, мы будем держать его здесь для будущего использования.

Обратите внимание, что мы используем двойное подчеркивание для этого construct метода.

Шаг 3 — Переменные класса

Далее мы установим некоторые переменные класса или свойства.

Префикс private определяет область действия переменной. В этом случае это означает, что переменная не может быть доступна из-за пределов класса.

Переменная $connectionId будет хранить наш поток соединения. Два других хранят статус и любые сообщения. $loginOk будет полезен при определении, правильно ли мы подключены.

Шаг 4 — Простая регистрация сообщений

Почти в каждом методе мы будем вызывать метод с именем logMessage . Это очень простой обработчик сообщений, который позволит нам захватывать любые сообщения, созданные нашим классом, чтобы мы могли предоставить пользователю обратную связь.

Обратите внимание, что мы не возвращаем return реальные сообщения из наших методов. Вместо этого мы возвращаем true или false , основываясь на том, была ли конкретная операция успешной. Это имеет свои преимущества, но также не детализирует пользователю, что происходит.

Добавьте следующие два метода, чтобы мы могли определить, что успешно.

Этот метод принимает переменную $message . Содержимое этой переменной затем сохраняется в нашем массиве класса благодаря строке: $this -> messageArray[] = $ message;

Поскольку $messageArray является переменной класса, мы можем получить к ней доступ через нотацию $this-> .

Внутри класса $this относится к самому объекту.

Чтобы получить сообщение, мы вызываем getMessages .

Этот метод является public методом. Как упоминалось ранее, private/public значение просто относится к области действия переменной или, в данном случае, к методу. Private метод (или переменная) не может быть доступен вне класса, в то время как public метод (или переменная) может.

Поскольку наша переменная является private, нам нужен способ доступа к ней. Мы делаем это, предоставляя нашему классу public метод, к которому мы можем получить доступ за пределами класса. Вы можете удивиться, почему мы не можем просто сделать общедоступной переменную messageArray . Мы можем; Тем не менее, это просто не очень хорошая практика.

Примечание. В Интернете есть множество примеров полнофункциональных обработчиков сообщений или посвященных им классов. Мы работаем над простой реализацией для целей этого урока.

Шаг 5 — Подключение

На этом шаге мы добавим метод connect . Это позволит нам подключиться к FTP-серверу.

Мы передаем информацию о соединении: сервер ( $server ), имя пользователя ( $ftpUser ) и пароль ( $ftpPassword ), чтобы позволить нам установить соединение.

Первая строка кода открывает FTP-соединение с ftp_connect к указанному серверу. Мы сохраняем наше соединение с переменной класса $connectionId , описанной выше.

Код ftp_login регистрирует нас на указанное соединение, передавая наш 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 и передавая ему данные нашего сервера.

Как видите, как только наш класс на месте, подключиться к нашему FTP-серверу очень просто!

Шаг 6b — Просмотр вывода

На последнем шаге мы можем заключить вызов connect в оператор if , как показано ниже. Тогда, если мы не сможем подключиться, зависимый код не будет выполнен. Затем мы можем вывести любые сообщения пользователю, такие как «подключен» или «не удалось».

Это нормально, хотя наш код быстро раздуется операторами IF/ELSE, если мы добавим это ко всем нашим вызовам. Вместо этого я хотел бы предложить альтернативу, которая сделает код немного чище и легче.

Помните методы обработки сообщений, которые мы добавили? Если вы хотите видеть сообщения, созданные классом — полезные для отладки/обратной связи — вы можете добавить следующий код после любого метода, который вы вызываете.

Он покажет сообщение класса.

Шаг 7 — Создание нашего первого каталога

Отлично, теперь пришло время сделать что-то полезное. Первый метод, который мы собираемся создать, это метод makeDir . Как и ожидалось, этот метод создаст для нас каталоги на сервере. Единственные параметры, которые мы передадим — это путь к каталогу и имя папки; мы назовем это $directory . Волшебная палочка здесь — встроенная функция ftp_mkdir . Она использует наш сохраненный « connectionId » и переданную переменную $directory для создания папки.

Добавьте следующий код в ваш файл ftp_class.php :

И, чтобы вызвать его из вашего файла index.php , добавьте:

Переменная $dir установлена на имя папки, которую мы хотим создать на сервере. В данном случае: «photos».

Следующая строка вызывает метод, который создаст папку.

Если вы получили сообщение об ошибке «Отказано в доступе», убедитесь, что вы можете писать в указанной папке. Вам может потребоваться создать папку в каталоге, например /httpdocs .

Шаг 8 — Загрузка файла

Продолжая, давайте загрузим фотографию, которая называется zoe.jpg . При загрузке файла нам нужно указать, какой тип файла мы загружаем — binary или ascii ? По сути, если вы загружаете текстовый файл, вы должны использовать ascii ; в противном случае он должен быть установлен как бинарный файл.

Мы начнем с установки array со всеми расширениями, которые мы должны использовать для загрузки типа ascii .

Затем мы извлекаем расширение нашего файла, чтобы мы могли проверить, является ли он одним из типов ascii . Мы определяем это, получая расширение загружаемого файла. Быстрый и грязный метод, который я использовал здесь это
«exploding», используя ‘ . ‘ в качестве разделителя. Он разделит файл на части и сохранит их в виде массива array . Используя другую встроенную функцию PHP «end», мы выбираем последний элемент массива array , который содержит наше расширение. Вот немного кода.

Затем мы проверяем, присутствует ли наше расширение в списке (с in_array) расширений файлов, которые должны быть загружены как тип ascii . Если он появляется в списке, мы устанавливаем переменную $mode в FTP_ASCII ; в противном случае мы предполагаем, что это двоичный тип, и присваиваем $mode значение FTP_BINARY .

ftp_put загружает файл из вашего локального местоположения в удаленный файл на FTP-сервере. Мы передаем ему наш « connectionId », путь к файлу, по который мы хотим загрузить ( $fileTo ), путь
файла, который мы хотим загрузить ( $file From ), и режим ( $mode ), который мы только что определили.

Затем добавьте следующий метод в ваш файл ftp_class.php :

Конечно, вы можете создать или загрузить любое имя папки по вашему желанию! Добавьте этот следующий фрагмент кода в файл index.php и внесите соответствующие изменения.

К настоящему времени вы уже должны были удостовериться, насколько просто использовать этот класс! Мы просто делаем отдельные вызовы для выполнения наших задач — все благодаря объектно-ориентированному программированию!

Шаг 9 — Просмотр файлов

Теперь давайте подтвердим, что наш файл находится в папке с photo . Мы можем сделать это, перейдя в папку « photo » на нашем сервере, а затем отобразить содержимое.

Метод changeDir использует « ftp_chdir » для изменения текущего каталога на ftp-сервере. Просто перейдите в каталог, чтобы изменить. Просто и мило.

getDirListing отобразит содержимое каталога, в котором вы находитесь, используя функцию » ftp_nlist «. Эта функция возвращает список файлов в данном каталоге. Текущий каталог установлен по умолчанию, поэтому вам не нужно указывать никаких параметров.

Если вы хотите, вы можете переопределить это, передав путь к каталогу в $directory , содержимое которого вы хотите просмотреть. Переменная $parameters по умолчанию равна -la . Это команда Linux для отображения дополнительной информации о каталоге. Не бойтесь удалить его или передать пустую строку.

ftp_class.php:

Метод getDirListing возвращает массив, который содержит наш массив array каталогов.

index.php

Ваш результат должен выглядеть так:

Шаг 10 — Загрузка файла

По мере продвижения к завершению этого урока мы переходим к загрузке файла. Метод начинается с того же кода, что и uploadFile , поскольку он определяет, является ли файл, который мы хотим загрузить, ascii или двоичным binary .

Для этого метода вы просто передаете имя файла (и, возможно, путь, в зависимости от того, находитесь ли вы в той же папке, что и файл, который вы хотите загрузить) файла для загрузки, и имя, которое вы хотите, чтобы этот файл имел на ваш клиентский компьютер.

Чтобы скачать файл, вам нужно вызвать ftp_get .

Он загружает файл с удаленного сервера на наш локальный компьютер. Он принимает следующий параметр: наш идентификатор соединения, путь и имя файла для сохранения локально (будет перезаписан, если он
уже существует) ( $fileTo ), местоположение и имя файла на удаленном сервере ( $fileFrom ) и режим ( $mode ).

ftp_class.php

Мы собираемся загрузить тот же файл, который мы загрузили, сохранив его под другим именем на нашем клиентском компьютере.

Примечание: еще раз, убедитесь, что ваши права установлены правильно!

Поскольку теперь мы должны находиться внутри нашей папки с фотографиями photo , мы не добавляем путь к переменной $fileFrom — только имя файла.

index.php

Шаг 11 — Завершение

Чтобы завершить наш класс, давайте добавим магический метод класса __deconstruct . Этот метод закрывает наше соединение, когда ссылка на наш объект больше не существует — возможно страница была закрыта. В любом случае этот код запускается и соединение закрывается. Как правило это хорошая практика включать его в код, хотя это не совсем необходимо.

Заключение

Хорошо что все получилось! Я надеюсь, что вы теперь лучше понимаете, как использовать FTP с PHP. Теперь у вас должны быть необходимые навыки для дальнейшего расширения этого класса для поддержки других распространенных задач, таких как переименование или удаление файлов и папок.

Обязательно сообщите нам, если вы создадите классные PHP FTP-клиенты!

XLIII. Функции для работы с FTP

Эти функции всегда доступны.

Для использования FTP функций, вы должны указать директиву —enable-ftp во время установки PHP 4 или —with-ftp при использовании PHP 3.

Версия PHP для Windows имеет встроенную поддержку данного расширения. Это означает, что для использования данных функций не требуется загрузка никаких дополнительных расширений.

Данное расширение не определяет никакие директивы конфигурации в php.ini .

Этот модуль использует один тип ресурса — идентификатор соединения с FTP сервером, возвращаемый функцией ftp_connect() или ftp_ssl_connect() .

Перечисленные ниже константы определены данным расширением и могут быть доступны только в том случае, если PHP был собран с поддержкой этого расширения или же в том случае, если данное расширение подгружается во время выполнения.

Дополнительная информация доступна в описании функции ftp_set_option() .

Следующие константы появились в PHP 4.3.0.

Дополнительная информация доступна в описании функции ftp_set_option() .

Автоматически определять позицию в файле, с которой начинается докачка при использовании команд GET и PUT (имеет смысл только совместно с FTP_AUTOSEEK )

Асинхронная операция завершилась неудачно

Асинхронная операция окончена

Асинхронная операция еще не завершена

Пример 1. Пример использования функций FTP

// вход с именем пользователя и паролем
$login_result = ftp_login ( $conn_id , $ftp_user_name , $ftp_user_pass );

// проверка соединения
if ((! $conn_id ) || (! $login_result )) <
echo «Не удалось установить соединение с FTP сервером!» ;
echo «Попытка подключения к серверу $ftp_server под именем $ftp_user_name!» ;
exit;
> else <
echo «Установлено соединение с FTP сервером $ftp_server под именем $ftp_user_name» ;
>

// закачивание файла
$upload = ftp_put ( $conn_id , $destination_file , $source_file , FTP_BINARY );

// проверка результата
if (! $upload ) <
echo «Не удалось закачать файл!» ;
> else <
echo «Файл $source_file закачен на $ftp_server под именем $destination_file» ;
>

// закрытие соединения
ftp_close ( $conn_id );
?>

Пред. Начало След.
fbsql_warnings Уровень выше ftp_alloc

Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:

XXXIX. Функции для работы с FTP

Эти функции всегда доступны.

Для использования FTP функций, вы должны указать директиву —enable-ftp во время установки PHP 4 или —with-ftp при использовании PHP 3.

Версия PHP для Windows имеет встроенную поддержку данного расширения. Это означает, что для использования данных функций не требуется загрузка никаких дополнительных расширений.

Данное расширение не определяет никакие директивы конфигурации в php.ini .

Этот модуль использует один тип ресурса — идентификатор соединения с FTP сервером, возвращаемый функцией ftp_connect() или ftp_ssl_connect() .

Перечисленные ниже константы определены данным расширением и могут быть доступны только в том случае, если PHP был собран с поддержкой этого расширения или же в том случае, если данное расширение подгружается во время выполнения.

Дополнительная информация доступна в описании функции ftp_set_option() .

Следующие константы появились в PHP 4.3.0.

Дополнительная информация доступна в описании функции ftp_set_option() .

Автоматически определять позицию в файле, с которой начинается докачка при использовании команд GET и PUT (имеет смысл только совместно с FTP_AUTOSEEK )

Асинхронная операция завершилась неудачно

Асинхронная операция окончена

Асинхронная операция еще не завершена

Пример 1. Пример использования функций FTP

// установка соединения
$conn_id = ftp_connect ( $ftp_server );

// вход с именем пользователя и паролем
$login_result = ftp_login ( $conn_id , $ftp_user_name , $ftp_user_pass );

// проверка соединения
if ((! $conn_id ) || (! $login_result )) <
echo «Не удалось установить соединение с FTP сервером!» ;
echo «Попытка подключения к серверу $ftp_server под именем $ftp_user_name!» ;
exit;
> else <
echo «Установлено соединение с FTP сервером $ftp_server под именем $ftp_user_name» ;
>

// закачивание файла
$upload = ftp_put ( $conn_id , $destination_file , $source_file , FTP_BINARY );

// проверка результата
if (! $upload ) <
echo «Не удалось закачать файл!» ;
> else <
echo «Файл $source_file закачен на $ftp_server под именем $destination_file» ;
>

// закрытие соединения
ftp_close ( $conn_id );
?>

It may seem obvious to others, but it had me stumped for nearly an hour! If you can connect to an ftp site but some functions (list, put, get etc) don’t work, then try using ftp_pasv and set passive mode on.

// setup $host and $file variables for your setup before here.

$hostip = gethostbyname ( $host );
$conn_id = ftp_connect ( $hostip );

// login with username and password
$login_result = ftp_login ( $conn_id , $ftp_user_name , $ftp_user_pass );

// IMPORTANT. turn passive mode on
ftp_pasv ( $conn_id , true );

if ((! $conn_id ) || (! $login_result )) <
echo «FTP connection has failed!» ;
echo «Attempted to connect to $host for user $ftp_user_name» ;
die;
> else <
echo «Connected to $host, for user $ftp_user_name
» ;
echo «Host IP is $hostip
» ;

// upload a file
if ( ftp_put ( $conn_id , $remote_file , $file , FTP_ASCII )) <
echo «successfully uploaded $file
» ;
> else <
echo «There was a problem while uploading $file
» ;
>

// close the connection
ftp_close ( $conn_id );
>
?>

If you prefer a OO-approach to the FTP-functions, you can use this snippet of code (PHP5 only! and does add some overhead). It’s just a «start-up», extend/improve as you wish.
You can pass all ftp_* functions to your object and stripping ftp_ of the function name. Plus, you don’t have to pass the ftp-resource as the first argument.

For example:
( $ftp , $file ); // Where $ftp is your ftp-resource
?>

Can become:
-> delete ( $file ); // Where $ftp is your FTP-object
?>

Code:
class FTP <

/* public Void __construct(): Constructor */
public function __construct ( $host , $port = 21 , $timeout = 90 ) <
$this -> ftp = ftp_connect ( $host , $port , $timeout );
>

/* public Void __destruct(): Destructor */
public function __destruct () <
@ ftp_close ( $this -> ftp );
>

/* public Mixed __call(): Re-route all function calls to the PHP-functions */
public function __call ( $function , $arguments ) <
// Prepend the ftp resource to the arguments array
array_unshift ( $arguments , $this -> ftp );

// Call the PHP function
return call_user_func_array ( ‘ftp_’ . $function , $arguments );
>

Here’s a little function that I created to recurse through a local directory and upload the entire contents to a remote FTP server.

In the example, I’m trying to copy the entire «iwm» directory located at /home/kristy/scripts/iwm to a remote server’s /public_html/test/ via FTP.

The only trouble is that for the line «if (!ftp_chdir($ftpc,$ftproot.$srcrela))», which I use to check if the directory already exists on the remote server, spits out a warning about being unable to change to that directory if it doesn’t exist.

But an error handler should take care of it.

My thanks to the person who posted the snippet on retrieving the list of files in a directory.

For the version of the script that echo’s it’s progress as it recurses & uploads, go to: http://pastebin.com/73784

// set the various variables
$ftproot = «/public_html/test/» ;
$srcroot = «/home/kristy/scripts/» ;
$srcrela = «iwm/» ;

// start ftp’ing over the directory recursively
ftpRec ( $srcrela );

// close the FTP connection
ftp_close ( $ftpc );

// enter the local directory to be recursed through
chdir ( $srcroot . $srcrela );

if ( $handle = opendir ( «.» ))
<
while ( false !== ( $fil = readdir ( $handle )))
<
if ( $fil != «.» && $fil != «..» )
<
// check if it’s a file or directory
if (! is_dir ( $fil ))
<
// it’s a file so upload it
ftp_put ( $ftpc , $ftproot . $srcrela . $fil , $fil , FTP_BINARY );
>
else
<
// it’s a directory so recurse through it
if ( $fil == «templates» )
<
// I want the script to ignore any directories named «templates»
// and therefore, not recurse through them and upload their contents
>
else
<
ftpRec ( $srcrela . $fil . «/» );
chdir ( «../» );
>
>
>
>
closedir ( $handle );
>
>
?>

I have written an OpenSource ZIP2FTP interface, which actually takes a given ZIP file and decompresses it in the folder on an FTP server you specify.

Therefore it may be quite interesting for you people interested in FTP, its adress is http://zip2ftp.alishomepage.com ; those who directly want the source may visit http://zip2ftp.alishomepage.com/?do=getSource

//If you want to move or replicate the folder hierarchy from your current server to another remote server. Then this will be helpful as this will browse the current server’s directory and at the same time it will copy that file in the remote server in the same directory.

//This script will copy all the files from this directory and subdirectory to another remote server via FTP

function rec_copy ( $source_path , $destination_path , $con )
<
ftp_mkdir ( $con , $destination_path );
ftp_site ( $con , ‘CHMOD 0777 ‘ . $destination_path );
ftp_chdir ( $con , $destination_path );

if ( is_dir ( $source_path ))
<
chdir ( $source_path );
$handle = opendir ( ‘.’ );
while (( $file = readdir ( $handle ))!== false )
<
if (( $file != «.» ) && ( $file != «..» ))
<
if ( is_dir ( $file ))
<
// here i am restricting the folder name ‘propertyimages’ from being copied to remote server. — VK
if( $file != «propertyimages» )
<
rec_copy ( $source_path . «/» . $file , $file , $con );
chdir ( $source_path );
ftp_cdup ( $con );
>
>
if ( is_file ( $file ))
<
$fp = fopen ( $file , «r» );
// this will convert spaces to ‘_’ so that it will not throw error. — VK
ftp_fput ( $con , str_replace ( » » , «_» , $file ), $fp , FTP_BINARY );
ftp_site ( $con , ‘CHMOD 0755 ‘ . str_replace ( » » , «_» , $file ));
>
>
>
closedir ( $handle );
>
>

// make a FTP connection —VK
$con = ftp_connect ( «69.18.213.131» , 21 );
$login_result = ftp_login ( $con , «username» , «password» );

// this is the root path for the remote server— VK
$rootpath = «mainwebsite_html» ;

// this is the physical path of the source directory. actually u can also use the relative path. — VK
$sourcepath = realpath ( «../» ). «/resdesk» ;

// this directory name will only change the top most directory and not the inner one — VK
$destination_dir_name = «resdesk_» . $account_id . «/» ;

rec_copy ( $sourcepath , $destination_dir_name , $con );
if ( function_exists ( «ftp_close» ))
<
ftp_close ( $con );
>
?>

Here’s another FTP interface over PHP (also uses MySQL)

PS: this script will ALSO allow you to download its source. So it becomes interesting for YOU PROGRAMMERS as well :D

I think what some other posts were trying to say which may need clarification is that in PHP 4.2.3, ftp_connect(«myhost.com») was failing most of the time, except it would work like every few minutes.

The fix is that ftp_connect seems to have a bug resolving addresses. If you do:

$hostip = gethostbyname($host);
$conn_ >
It seems to solve the problem.
(Other users referred to an ftpbuf() error. not sure what that is, but this should fix it.)

connection to a ftp server across proxy

$ftp_server = «proxy»; f.e. 123.456.789.10
$ftp_user_name = «username@ftpserver»; f.e. exampleuk@www.example.uk
$ftp_user_pass = «password»;

$conn_ > $login_result = ftp_login( $conn_id, $ftp_user_name, $ftp_user_pass );

PHP 5 FTP Функции

PHP FTP введение

Функции FTP предоставляют клиенту доступ к файловым серверам через протокол передачи файлов (FTP).

Функции FTP используются для открытия, входа и закрытия подключений, а также для загрузки, скачивания, переименования, удаления и получения информации о файлах с файловых серверов. Не все функции FTP будут работать с каждым сервером или возвращать одинаковые результаты. Функции FTP стали доступны с PHP 3.

Если вы хотите только читать или записывать в файл на FTP-сервере, рассмотрите возможность использования оболочки FTP://с функциями файловой системы, которые обеспечивают более простой и интуитивно понятный интерфейс.

Установки

Для работы этих функций необходимо скомпилировать PHP с—Enable-FTP.

Версия PHP для Windows имеет встроенную поддержку этого расширения.

Работа по FTP

FTP — File Transfer Protocol (букв. «протокол передачи файлов») — стандартный протокол, предназначенный для передачи файлов.
FTP-клиент — это программа, позволяющая с помощью FTP-доступа к аккаунту осуществлять его администрирование, т.е. загружать на сервер файлы, редактировать и обновлять их. FTP-клиент устанавливается на компьютере пользователя.

Настройка FTP-клиента

По умолчанию для каждого аккаунта на хостинге SpaceWeb предоставлен основной FTP-доступ.
Для того, чтобы подключиться к своему аккаунту по FTP, необходимо должным образом настроить FTP-клиент.

В FTP-клиенте необходимо задать следующие параметры:

  • Имя пользователя — совпадает с логином для панели управления.
  • Пароль — совпадает с паролем для входа в Панель управления.
  • Имя сервера — можно указать IP-адрес, сообщающийся в письме с уведомлением о создании аккаунта. Его всегда можно узнать в панели управления аккаунтом в колонке слева.
    Либо, можно указать любое доменное имя сайта, размещённого на аккаунте, к которому настраивается доступ.
  • Порт — 21

Дополнительные FTP-аккаунты

Основной FTP-доступ используется клиентом для доступа ко всем файлам, находящимся на аккаунте.

Панель управления SpaceWeb предоставляет возможность создания дополнительных FTP-аккаунтов.

Дополнительные FTP-аккаунты предназначены для выделения ограниченного доступа. Например, если на одном аккаунте размещено несколько сайтов и над каждым сайтом работает отдельный технический специалист, то удобно создать и предоставить им различные FTP-аккаунты. Таким образом каждый специалист будет иметь доступ к файлам только того сайта, с которым он работает.

Логин и пароль для дополнительного FTP-аккаунта задаются при его создании.

Методы работы по FTP

При работе по FTP можно передавать отдельные файлы, группы файлов или архивы.
Мы рекомендуем использовать архивацию. Передача одного архива производится намного быстрее, нежели передача большого количества файлов небольшого объема.

Режимы работы FTP-соединения

Существует два вида режимов:

  • Активный
    В активном режиме клиент создает управляющее TCP-соединение с сервером и отправляет серверу свой IP-адрес и произвольный номер клиентского порта, после чего ждёт, пока сервер не откроет TCP-соединение с этим адресом и номером порта.
  • Пассивный
    В пассивном режиме клиент передаёт по управляющему соединению команду PASV, и затем получает от сервера его IP-адрес и номер порта, которые будут использованы клиентом для открытия соединения для передачи файлов.

Основное отличие между режимами — это сторона, которая открывает соединение для передачи данных. В активном режиме, клиент должен принять соединение от FTP-сервера. В пассивном режиме, клиент всегда сам подключается к серверу.

Если клиент находится во внутренней сети, то, с высокой долей вероятности, активный режим соединения не будет работать.

Примеры распространенных FTP-клиентов

  • FileZilla — Инструкция по настройке
  • WinSCP — Инструкция по настройке
  • SmartFTP
  • Far
  • CuteFTP
  • Total Commander
  • FireFTP — плагин для браузера Firefox

Для работы с папками и файлами можно воспользоваться удобным файловым менеджером, предоставленным в Панели управления аккаунтом.

Илон Маск рекомендует:  border-top в CSS
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL