[Разработка под Android] Работа с FTP протоколом в Android. Пример

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
21-Фев-2021 02:30

Всем привет! Это будет очень маленькая статья. Наша задача тут: подключиться к локальному серверу FTP (я выбрала FileZilla) и отправить туда чего-нибудь используя (очевидно) FTP протокол.
Итак, капелька теории:
FTP (File Transfer Protocol) — протокол передачи файлов по сети.
Для работы по FTP нужны двое: FTP-сервер и FTP-клиент.
Сервер обеспечивает доступ по логину и паролю к нужным файлам и, соответственно, показывает пользователю только те файлы и папки, к которым он имеет доступ.
Клиент — программа для FTP-соединения. Основная идея в том, чтобы пользователь мог оперировать файловыми данными на стороне сервера: просматривать, редактировать, копировать, загружать и удалять.
Все логично.
В отличие, скажем, от того же HTTP FTP использует в качестве модели соединения двойное подключение. При этом один канал является управляющим, через который поступают команды серверу и возвращаются его ответы (обычно через TCP-порт 21), а через остальные происходит собственно передача данных, по одному каналу на каждую передачу. Поэтому в рамках одной сессии по протоколу FTP можно передавать одновременно несколько файлов, причём в обоих направлениях.
Если расписать процесс установки соединения и дальнейшей передачи данных по пунктам, то получится примерно следующее:
  • Пользователь активирует клиентское приложение и соединяется с сервером, введя логин и пароль.
  • Устанавливается управляющее соединение между соответствующими модулями — интерпретаторами протокола со стороны клиента и сервера.
  • Пользователь посредством клиента посылает команды серверу, определяющие различные параметры FTP-соединения (активный или пассивный режим, FTP — порт, вид передачи данных, их тип), а также директивы для действий, которые юзер намерен осуществить (например, удалить, переименовать, закачать файл и т.д.).
  • Далее один из участников (к примеру, клиент), являющийся пассивным, становится в режим ожидания открытия соединения на FPT — порт, который задан для передачи информации.
    Затем активный участник открывает соединение и начинает передавать данные по предназначенному для этого каналу.
  • По завершении передачи, это соединение закрывается, но управляющий канал между интерпретаторами остается открытым, вследствие чего пользователь в рамках той же сессии может вновь открыть передачу данных.

FTP — соединение по умолчанию происходит через порт 21, если не установлен другой порт.

Реализация
В данном случае будем использовать класс FTPClient из библиотеки Apache (org.apache.commons.net.ftp.FTPClient). Создаем объект класса, устанавливаем таймаут. Затем мы должны сначала подключиться к серверу с помощью connect, прежде чем что-либо делать (и не забыть отключиться после того, как все сделаем). В connect в качестве первого параметра пишем локальный адрес хоста, вторым аргументом — порт для подключения. Также необходимо проверить код ответа FTP (слишком очевидно, но все же), чтобы убедиться, что соединение было успешным.
import org.apache.commons.net.ftp.FTP
import org.apache.commons.net.ftp.FTPClient
import org.apache.commons.net.ftp.FTPReply
...
val con = FTPClient()
        con.connectTimeout = ххх
        con.connect("192.168.0.105", 21)
        if (FTPReply.isPositiveCompletion(con.replyCode)) {
                //все круто
        }

Хорошо, мы подключились к серверу. Что дальше? Теперь необходимо пройти авторизацию под именем пользователя, которого мы, собственно, создали для этого. Но перед этим нужно установить для текущего режима подключения к данным значение PASSIVE_LOCAL_DATA_CONNECTION_MODE с помощью команды enterLocalPassiveMode(). Это значит, что все передачи будут происходить между клиентом и сервером, и что сервер находится в пассивном режиме, ожидая подключения клиента для инициализации передачи данных. (например, ACTIVE_LOCAL_DATA_CONNECTION_MODE подразумевает, что инициатором подключения будет выступать сервер).
После в login пишем логин и пароль пользователя. storeFile() сохраняет файл на сервере, используя заданное имя и принимая входные данные из заданного InputStream. У меня была задача периодически писать в определенный файл на сервере, поэтому это выглядит так:
con.enterLocalPassiveMode()
                if (con.login("nad", "nad")) { //вводим логин и пароль (да, вот так в открытом виде)
                    con.setFileType(FTP.BINARY_FILE_TYPE)
                    val msg = "your_msg"
                    val msg_bytes: InputStream = ByteArrayInputStream(msg.toByteArray())
                    val result: Boolean = con.storeFile("/sms.txt", msg_bytes)
                    msg_bytes.close()
                    if (result) Log.v("upload result", "succeeded")
                    con.logout()
                    con.disconnect()
                }
            }
             catch (ex: IOException) {
                ex.printStackTrace()
                return Result.failure()
            }

Если же вы хотите скопировать свой файл на сервер целиком, можно сделать так (суть не особо меняется, но вдруг кому-то нужно):
val file = File("путь до файла")
val msg_bytes = FileInputStream(file)

В целом это все, что вам может понадобиться. И, конечно, немного о настройке локального FTP сервера. У меня это, как и писала ранее, FileZilla. Все оставляем по дефолту. Создаем пользователя и присваиваем ему папку на хосте, из которой он может читать/писать/удалять и т.д.

Вот и все. Запускаем и смотрим логи на сервере. И вот чего должны получить:

Удачи!
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_razrabotka_pod_android (Разработка под Android), #_android, #_ftp, #_razrabotka_pod_android (
Разработка под Android
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 23-Ноя 04:41
Часовой пояс: UTC + 5