Робота з FTP протоколом на Visual Basic (исходники), Різне, Програмування, статті

У моїй останньої розробки потрібно було використовувати функції роботи з FTP. Спочатку для цієї мети я використав Internet Transfer Controls, але незабаром зрозумів, що цей компонент заточений більше на роботу з Http. У ITC були проблеми з серверами, на яких було встановлено не мікрософтівської ПО (ну, наприклад Apache). Тоді я вирішив написати власний FTP компонент у вигляді класу (сукупності об’єктів або функцій в групі з їх властивості і поведінки). Після годин пошуку в MSDN я виявив дуже цікаві функції FtpPutFile, FtpGetFile, FtpCreateDirectory. Робота цих функцій ставала можливою при отриманні даних (хендла) від функції InternetConnect, яка використовується для звернення до певних портів адреси (IP). Але і їй потрібна інформація від функції InternetOpen. Таким чином, для використання будь-яких FTP команд необхідно послідовно викликати ці функції. При завершенні роботи потрібно викликати функцію InternetCloseHandle два рази, щоб закрити FTP і Internet сесії.

Правильна послідовність функцій:


Мабуть, настав час підтвердити теоретичну частину статті прикладами. Для початку саме основне – функція FTPGetFile для отримання файлу від сервера. Ось так ця функція оголошується:





Private Declare Function FtpGetFile _
Lib “wininet.dll” Alias “FtpGetFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszRemoteFile As String, _
ByVal lpszNewFile As String, _
ByVal fFailIfExists As Boolean, _
ByVal dwFlagsAndAttributes As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean

Як я вже писав, нам знадобляться функції InternetOpen і InternetConnect. Вони оголошуються так:





Private Declare Function InternetOpen _
Lib “wininet.dll” Alias “InternetOpenA” ( _
ByVal sAgent As String, _
ByVal nAccessType As Long, _
ByVal sProxyName As String, _
ByVal sProxyBypass As String, _
ByVal nFlags As Long) As Long
Private Declare Function InternetConnect _
Lib “wininet.dll” Alias “InternetConnectA” ( _
ByVal hInternetSession As Long, _
ByVal sServerName As String, _
ByVal nServerPort As Integer, _
ByVal sUserName As String, _
ByVal sPassword As String, _
ByVal nService As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Long

Розглянемо кожен з чотирьох кроків окремо.

Крок перший: Підключення до Інтернет






hINetSession = InternetOpen(“MyFTPClient”, 0, vbNullString,  vbNullString, 0)

Перший параметр (sAgent) вказує на ім’я програми, яка викликає функцію. Мабуть, тут можна писати все, що завгодно. Другий параметр (nAccessType) може приймати всього три значення – 0,1 і 3. Він визначає, чи ми використаємо проксі чи ні. При значенні рівному 1 ми конектиться прямо. При 3-х ми використовуємо проксі. При цьому адреса проксі потрібно задати в параметрі sProxyName і порт в параметрі sProxyBypass. У даному прикладі для з’єднання я встановив значення 0, при якому функція бере всю інформацію з реєстру (тобто використовує настройки IE). Т.к. ми не визначаємо проксі-сервер безпосередньо, то третій і четвертий параметри приймають значення vbNullString. Останній параметр dwFlags визначає роботу функції. Нічого нестандартного в цьому випадку нам не потрібно, тому просто ставимо 0.

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

Крок другий: виробляємо коннект






hSession = InternetConnect(hINetSession, “ftp.microsoft.com”,
“21”, “anonymous”, “guest”, INTERNET_SERVICE_FTP, 0, 0)

Перший параметр InternetConnect являє собою хендл, отриманий при виконанні InternetOpen. Другий – урл або Ip хоста, до якого ми приєднуємося (при цьому ftp:// опускається). Наступним параметром йде порт. Я виставив значення порту рівне 21, але якщо ви поставите 0, то нічого страшного не станеться. Просто програма буде коннектіться через порт за замовчуванням (як раз 21). Далі ми передаємо логін і пароль. Будьте обережні! При дізассмеблірованіі всі ваші паролі можуть потрапити в руки особливо старанних крякери. Наступним параметром ми визначаємо тип використовуваного сервісу. Я використовував зарезервовану константу INTERNET_SERVICE_FTP, яка має значення 1. Також можуть бути використані наступні значення:






Private Const INTERNET_SERVICE_FTP = 1
Private Const INTERNET_SERVICE_GOPHER = 2
Private Const INTERNET_SERVICE_HTTP = 3

Зараз нас цікавить тільки FTP. Якщо виставити 0, то функція сама визначить, що нам потрібно. В цьому випадку в параметрі sServerName слід вказати повний урл (ftp://ftp.pesh.com)

Параметр dwFlags ми могли встановити на & H8000000 (або INTERNET_FLAG_PASSIVE), якби нам треба було працювати в FTP в пасивному режимі. Тут ми просто пишемо 0. Останній параметр dwContext визначає необхідність повернення функцією значень. Нам це не потрібно, тому 0.

Крок третій: виклик FTP функцій (наприклад, FTPGetFile)


Спочатку ми оголосимо цю функцію:





Private Declare Function FtpGetFile _
Lib “wininet.dll” Alias “FtpGetFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszRemoteFile As String, _
ByVal lpszNewFile As String, _
ByVal fFailIfExists As Boolean, _
ByVal dwFlagsAndAttributes As Long, _
ByVal dwFlags As Long, _
ByVal dwContext As Long) As Boolean

Потім нам залишається тільки викликати її:





If FtpGetFile(hSession, “dirmap.htm”, “c:dirmap.htm”,  False, 0, 1, 0) = False Then
MsgBox “Call to FtpGetFile Failed!”
End If

Першим йде хендл від функції InternetConnect. Далі ім’я (або повний шлях) до файлу на віддаленому сервері. Третій параметр – шлях до місця призначення. Параметр № 4 fFailExists визначає, як буде вести себе програма, якщо вона виявить, що файл з таким ім’ям вже існує. Значення false вказує на те, що такі файли будуть записуватись. Атрибути, що привласнюються локальному файлу, задаються в параметрі dwFlagAttributes. Це можна зробити і після. За формат передачі даних відповідає параметр dwFlags: ASCII = 1, Binary = 2. Останній параметр також відповідає за повернення значень.

Пункт четвертий, заключний: закриваємо хендл


Хендл закриваються в порядку, протилежному їх відкриття. Спочатку закриємо hSession, а потім InetSession. Для цього використовуємо функцію InternetCloseHandle.





Private Declare Function InternetCloseHandle _
Lib “wininet.dll” (ByVal hInet As Long) As Integer

Так вона викликається:





Call InternetCloseHandle(hSession)
Call InternetCloseHandle(hINetSession)

Готово! Ми скачали файл. Тепер розберемося з іншими функціями.

Для відправки файлу на сервер виконуємо кроки 1 і 2 та викликаємо функцію FTPPutFile, яка виглядає так:





Private Declare Function FtpPutFile _
Lib “wininet.dll” Alias “FtpPutFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszLocalFile As String, _
ByVal lpszRemoteFile As String, _
ByVal dwFlags As Long,
ByVal dwContext As Long) As Boolean

Як бачите, дуже схоже на FTPGetFile.

Спочатку йде хендл від InternetConnect, шлях та ім’я локального і “віддаленого” файлів. Параметр dwFlags задає тип передачі ASCII = 1, Binary = 2; останній аргумент опускаємо.





If FtpPutFile(hSession, “c:MyFile.txt”, “shared.txt”, 1, 0) = False Then
MsgBox “The call to FtpPutFile failed.”
End If

Виклик функції може виявитися неуспішним, якщо у користувача немає прав закачувати файли на сервер.

Видаляє файл





Private Declare Function FtpDeleteFile _
Lib “wininet.dll” Alias “FtpDeleteFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszFileName As String) As Boolean

Тут просто виставляємо хендл та ім’я файлу, що видаляється. Знову може не спрацювати при відсутності прав на видалення.

ПЕРЕЙМЕНУВАННЯ





Private Declare Function FtpRenameFile _
Lib “wininet.dll” Alias “FtpRenameFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszExisting As String, _
ByVal lpszNewName As String) As Boolean

Знову потрібно тільки хендл та імена файлів (старе і нове)

ОТРИМУЄМО СПИСОК файлів і директорій НА СЕРВЕР

Як ви могли помітити, всі вищеописані функції дуже прості. Ось приклад складніше. Значення функції можуть виводиться в Лістбокс або його аналог. Нам будуть потрібні дві функції FtpFindFirstFile і InternetFindNextFile:






Private Declare Function FtpFindFirstFile _
Lib “wininet.dll” Alias “FtpFindFirstFileA” ( _
ByVal hFtpSession As Long, _
ByVal lpszSearchFile As String, _
ByRef lpFindFileData As WIN32_FIND_DATA,
ByVal dwFlags As Long, _
ByVal dwContent As Long) As Long

Private Declare Function InternetFindNextFile _
Lib “wininet.dll” Alias “InternetFindNextFileA” ( _
ByVal hFind As Long, _
ByRef lpvFindData As WIN32_FIND_DATA) As Long


Ці функції повертають ненульове значення при виявленні файлу і 0, якщо відбулася помилка. Для того щоб визначити реальна чи це помилка або просто більше немає файлів потрібно, перевірити значення Err.LastDllError. Якщо воно дорівнює ERROR_NO_MORE_FILES (= 18), то все нормально, якщо немає, то справа наша погано.

Обидві ці функції мають параметр WIN32_FIND_DATA, який представляє собою тип або структуру, яка визначається юзером.





Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * 260
cAlternate As String * 14
End Type

Підструктура FILENAME:





Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type

Далі я привожу приклад заповнення ListBox файлами і директоріями з сервера. Вважаємо, що ви вже отримали FTP хендл c ім’ям hSession.





Private Sub ListFiles()
Dim hFile As Long ” This is a file handle
Dim fd As WIN32_FIND_DATA
hFile = FtpFindFirstFile(hSession, “*.*”, fd, 0, 0)
If hFile = 0 Then
If Err.LastDLLError = ERROR_NO_MORE_FILES Then
MsgBox “No files found”
Exit Sub
Else
MsgBox “Some error occurred”
Exit Sub
End If
End If
Do
List1.AddItem fd.cFileName
Loop While InternetNextFile(hFile, fd) <> 0
“Close the file handle
Call InternetCloseHandle(hFile)
End Sub

Висновок


Як ви бачите, описувати FTP функції дуже просто. Звичайно, є ще багато різних функцій, типу створення директорії, але їх також легко написати, головне не забувайте закривати хендл.


Схожі статті:


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

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*