Сеансы FTP

WinINet позволяет приложениям перемещаться по каталогам и файлам на ftp-сервере и управлять ими. Так как прокси-серверы CERN не поддерживают FTP, приложения, использующие исключительно прокси-сервер CERN, должны использовать функцию InternetOpenUrl . Дополнительные сведения об использовании InternetOpenUrl см. в разделе Прямой доступ к URL-адресам.

Чтобы начать сеанс FTP, создайте дескриптор сеанса с помощью InternetConnect .

WinINet позволяет выполнять следующие действия на FTP-сервере:

  • Переход между каталогами.
  • Перечисление, создание, удаление и переименование каталогов.
  • Переименование, отправка, скачивание и удаление файлов.

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

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

Используйте функцию FtpCreateDirectory для создания новых каталогов. Эта функция использует дескриптор сеанса, созданный InternetConnect, и создает каталог, указанный строкой, передаваемой функции. Строка может содержать имя каталога относительно текущего каталога или полный путь к каталогу.

Чтобы переименовать файлы или каталоги, приложение может вызвать FtpRenameFile. Эта функция заменяет исходное имя новым именем, переданным в функцию. Имя файла или каталога может быть относительно текущего каталога или полного имени.

Для отправки или размещения файлов на FTP-сервере приложение может использовать ftpPutFile или FtpOpenFile (вместе с InternetWriteFile). FtpPutFile можно использовать, если файл уже существует локально, а FtpOpenFile и InternetWriteFile — для записи данных в файл на FTP-сервере.

Чтобы скачать или получить файлы, приложение может использовать ftpGetFile или FtpOpenFileInternetReadFile). FtpGetFile используется для получения файла с FTP-сервера и его локального хранения, в то время как FtpOpenFile и InternetReadFile можно использовать для управления расположением скачанных сведений (например, приложение может отображать информацию в поле редактирования).

Удалите файлы на FTP-сервере с помощью функции FtpDeleteFile . Эта функция удаляет имя файла, которое относится либо к текущему каталогу, либо к полному имени файла с FTP-сервера. Для FtpDeleteFile требуется дескриптор сеанса, возвращаемый InternetConnect.

Дескрипторы функций FTP

Для правильной работы функций FTP требуются определенные типы дескрипторов HINTERNET . Эти дескрипторы должны быть созданы в определенном порядке, начиная с корневого дескриптора, созданного InternetOpen. После этого InternetConnect может создать дескриптор сеанса FTP.

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

Функции FTP, зависящие от дескриптора сеанса FTP, возвращаемого internetconnect

На следующей схеме показаны две функции, возвращающие дескриптора HINTERNET , и зависимые от них функции. Затеняемые поля представляют функции, возвращающие дескрипторы HINTERNET , а обычные — функции, использующие дескриптор HINTERNET , созданный функцией, от которой они зависят.

функции FTP, возвращающие дескрипторы hinternet

Дополнительные сведения см. в разделе Дескрипторы HINTERNET.

Использование функций WinINet для сеансов FTP

Во время сеансов FTP используются следующие функции. Эти функции не распознаются прокси-серверами CERN. Приложения, которые должны работать через прокси-серверы CERN, должны использовать InternetOpenUrl и получать доступ к ресурсам напрямую. Дополнительные сведения о прямом доступе к ресурсам см. в статье Прямой доступ к URL-адресам.

Функция Описание
FtpCreateDirectory Создает новый каталог на сервере. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpDeleteFile Удаляет файл с сервера. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpFindFirstFile Запускает перечисление файлов или поиск файлов в текущем каталоге. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpGetCurrentDirectory Возвращает текущий каталог клиента на сервере. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpGetFile Извлекает файл с сервера. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpOpenFile Инициирует доступ к файлу на сервере для чтения или записи. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpPutFile Записывает файл на сервер. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpRemoveDirectory Удаляет каталог на сервере. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpRenameFile Переименовывает файл на сервере. Для этой функции требуется дескриптор, созданный InternetConnect.
FtpSetCurrentDirectory Изменяет текущий каталог клиента на сервере. Для этой функции требуется дескриптор, созданный InternetConnect.
InternetWriteFile Записывает данные в открытый файл на сервере. Для этой функции требуется дескриптор, созданный ftpOpenFile.

 

Запуск сеанса FTP

Приложение устанавливает сеанс FTP, вызывая InternetConnect для дескриптора, созданного InternetOpen. InternetConnect требуется имя сервера, номер порта, имя пользователя, пароль и тип службы (для которого необходимо задать значение INTERNET_SERVICE_FTP). Для пассивной семантики FTP приложение также должно установить флаг INTERNET_FLAG_PASSIVE .

Для номера порта можно использовать значения INTERNET_DEFAULT_FTP_PORT и INTERNET_INVALID_PORT_NUMBER. INTERNET_DEFAULT_FTP_PORT использует ftp-порт по умолчанию, но тип службы по-прежнему должен быть задан. INTERNET_INVALID_PORT_NUMBER использует значение по умолчанию для указанного типа службы.

Для значений имени пользователя и пароля можно задать значение NULL. Если для обоих значений задано значение NULL, InternetConnect использует "anonymous" для имени пользователя и адрес электронной почты пользователя для пароля. Если только пароль имеет значение NULL, имя пользователя, переданное в InternetConnect , используется в качестве имени пользователя, а для пароля используется пустая строка. Если ни то, ни другое значение не равно NULL, используются имя пользователя и пароль, предоставленные InternetConnect .

Перечисление каталогов

Для перечисления каталога на FTP-сервере требуется создать дескриптор ftpFindFirstFile. Этот дескриптор является ветвью дескриптора сеанса, созданного InternetConnect. FtpFindFirstFile находит первый файл или каталог на сервере и возвращает их в WIN32_FIND_DATA структуре. Используйте InternetFindNextFile , пока не вернется ERROR_NO_MORE_FILES. Этот метод находит все последующие файлы и каталоги на сервере. Дополнительные сведения о InternetFindNextFile см. в разделе Поиск следующего файла.

Чтобы определить, является ли файл, полученный ftpFindFirstFile или InternetFindNextFile, каталогом, проверка элемент dwFileAttributes структуры WIN32_FIND_DATA, чтобы узнать, равен ли он FILE_ATTRIBUTE_DIRECTORY.

Если приложение вносит изменения на FTP-сервере или FTP-сервер часто меняется, флаги INTERNET_FLAG_NO_CACHE_WRITE и INTERNET_FLAG_RELOAD должны быть установлены в ftpFindFirstFile. Эти флаги гарантируют, что сведения о каталоге, извлекаемые с FTP-сервера, являются актуальными.

После завершения перечисления каталога приложение должно выполнить вызов InternetCloseHandle для дескриптора, созданного ftpFindFirstFile. Пока этот дескриптор не будет закрыт, приложение не сможет снова вызвать FtpFindFirstFile для дескриптора сеанса, созданного InternetConnect. Если вызов FtpFindFirstFile выполняется в том же дескрипторове сеанса перед закрытием предыдущего вызова той же функции, функция завершается сбоем, возвращая ERROR_FTP_TRANSFER_IN_PROGRESS.

В следующем примере содержимое каталога FTP перечисляется в элемент управления "Список". Параметр hConnection — это дескриптор, возвращаемый функцией InternetConnect после установки сеанса FTP. Пример исходного кода для функции InternetErrorOut, на который ссылается в этом примере, можно найти в разделе Обработка ошибок.

#include <windows.h>
#include <strsafe.h>
#include <wininet.h>

#pragma comment(lib, "wininet.lib")
#pragma comment(lib, "user32.lib")

#define  FTP_FUNCTIONS_BUFFER_SIZE          MAX_PATH+8

BOOL WINAPI DisplayFtpDir(
                           HWND hDlg,
                           HINTERNET hConnection,
                           DWORD dwFindFlags,
                           int nListBoxId )
{
  WIN32_FIND_DATA dirInfo;
  HINTERNET       hFind;
  DWORD           dwError;
  BOOL            retVal = FALSE;
  TCHAR           szMsgBuffer[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR           szFName[FTP_FUNCTIONS_BUFFER_SIZE];
  
  SendDlgItemMessage( hDlg, nListBoxId, LB_RESETCONTENT, 0, 0 );
  hFind = FtpFindFirstFile( hConnection, TEXT( "*.*" ), 
                            &dirInfo, dwFindFlags, 0 );
  if ( hFind == NULL )
  {
    dwError = GetLastError( );
    if( dwError == ERROR_NO_MORE_FILES )
    {
      StringCchCopy( szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
        TEXT( "No files found at FTP location specified." ) );
      retVal = TRUE;
      goto DisplayDirError_1;
    }
    StringCchCopy( szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
      TEXT( "FtpFindFirstFile failed." ) );
    goto DisplayDirError_1;
  }

  do
  {
    if( FAILED( StringCchCopy( szFName, FTP_FUNCTIONS_BUFFER_SIZE,
                  dirInfo.cFileName ) ) ||
        ( ( dirInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) &&
        ( FAILED( StringCchCat( szFName, FTP_FUNCTIONS_BUFFER_SIZE,
         TEXT( " <DIR> " ) ) ) ) ) )
    {
      StringCchCopy( szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
        TEXT( "Failed to copy a file or directory name." ) );
      retVal = FALSE;
      goto DisplayDirError_2;
    }
    SendDlgItemMessage( hDlg, nListBoxId, LB_ADDSTRING, 
                        0, (LPARAM) szFName );
  } while( InternetFindNextFile( hFind, (LPVOID) &dirInfo ) );

  if( ( dwError = GetLastError( ) ) == ERROR_NO_MORE_FILES )
  {
    InternetCloseHandle(hFind);
    return( TRUE );
  }
  StringCchCopy( szMsgBuffer, FTP_FUNCTIONS_BUFFER_SIZE,
    TEXT( "FtpFindNextFile failed." ) );

DisplayDirError_2:
  InternetCloseHandle( hFind );
DisplayDirError_1:
  MessageBox( hDlg,
    (LPCTSTR) szMsgBuffer,
    TEXT( "DisplayFtpDir( ) Problem" ),
    MB_OK | MB_ICONERROR );
  return( retVal );
}

Функции FtpGetCurrentDirectory и FtpSetCurrentDirectory обрабатывают навигацию по каталогам.

FtpGetCurrentDirectory возвращает текущий каталог приложения на FTP-сервере. Путь к каталогу из корневого каталога на FTP-сервере включен.

FtpSetCurrentDirectory изменяет рабочий каталог на сервере. Сведения о каталоге, передаваемые в FtpSetCurrentDirectory , могут быть частичным или полным именем пути относительно текущего каталога. Например, если приложение в настоящее время находится в каталоге public/info, а путь — ftp/example, FtpSetCurrentDirectory изменит текущий каталог на public/info/ftp/example.

В следующем примере используется дескриптор сеанса FTP hConnection, возвращаемый InternetConnect. Новое имя каталога берется из поля редактирования родительского диалогового окна, idC которого передается в параметре nDirNameId . Перед изменением каталога функция извлекает текущий каталог и сохраняет его в том же поле ввода. Код souce для функции DisplayFtpDir, вызываемой в конце, указан выше.

BOOL WINAPI ChangeFtpDir( HWND hDlg, 
                          HINTERNET hConnection,
                          int nDirNameId, 
                          int nListBoxId )
{
  DWORD dwSize;
  TCHAR szNewDirName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szOldDirName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR* szFailedFunctionName;

  dwSize = FTP_FUNCTIONS_BUFFER_SIZE;

  if( !GetDlgItemText( hDlg, nDirNameId, szNewDirName, dwSize ) )
  {
    szFailedFunctionName = TEXT( "GetDlgItemText" );
    goto ChangeFtpDirError;
  }

  if ( !FtpGetCurrentDirectory( hConnection, szOldDirName, &dwSize ))
  {
    szFailedFunctionName = TEXT( "FtpGetCurrentDirectory" );
    goto ChangeFtpDirError;
  }

  if( !SetDlgItemText( hDlg, nDirNameId, szOldDirName ) )
  {
    szFailedFunctionName = TEXT( "SetDlgItemText" );
    goto ChangeFtpDirError;
  }

  if( !FtpSetCurrentDirectory( hConnection, szNewDirName ) )
  {
    szFailedFunctionName = TEXT( "FtpSetCurrentDirectory" );
    goto ChangeFtpDirError;
  }
  return( DisplayFtpDir( hDlg, hConnection, 0, nListBoxId ) );

ChangeFtpDirError:
  InternetErrorOut( hDlg, GetLastError( ), szFailedFunctionName );
  DisplayFtpDir( hDlg, hConnection, INTERNET_FLAG_RELOAD, nListBoxId);
  return( FALSE );
}

Управление каталогами на FTP-сервере

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

Функция FtpCreateDirectory принимает допустимый дескриптор сеанса FTP и строку, завершающуюся null, которая содержит полный путь или имя относительно текущего каталога, и создает каталог на FTP-сервере.

В следующем примере показаны два отдельных вызова FtpCreateDirectory. В обоих примерах hFtpSession — это дескриптор сеанса, созданный функцией InternetConnect , а корневой каталог — текущий каталог.

/* Creates the directory "test" in the current (root) directory. */
FtpCreateDirectory( hFtpSession, "test" );

/* Creates the directory "example" in the test directory. */
FtpCreateDirectory( hFtpSession, "\\test\\example" );

Функция FtpRemoveDirectory принимает дескриптор сеанса и строку, завершающуюся значением NULL, которая содержит полный путь или имя относительно текущего каталога, и удаляет этот каталог с FTP-сервера.

В следующем примере показаны два примера вызовов FtpRemoveDirectory. В обоих вызовах hFtpSession — это дескриптор сеанса, созданный функцией InternetConnect , а корневой каталог — текущий каталог. В корневом каталоге есть каталог с именем test, а в каталоге test — каталог с именем example.

/* Removes the "example" directory (plus any files/directories it contains) from the "test" directory. */
FtpRemoveDirectory(hFtpSession,"\\test\\example");

/* Removes the "test" directory (plus any files/directories it contains) from the root directory. */
FtpRemoveDirectory(hFtpSession, "test");
FtpRemoveDirectory(hFtpSession,TEXT("\\test\\example"));
/* Removes the "example" directory and any files or 
directories contained in it from the "test" directory. */

FtpRemoveDirectory(hFtpSession, TEXT("test"));
/* Removes the "test" directory and any files or 
directories contained in it from the root directory. */

В следующем примере создается новый каталог на FTP-сервере. Новое имя каталога берется из поля редактирования родительского диалогового окна, idC которого передается в параметре nDirNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP. Исходный код функции DisplayFtpDir, вызываемой в конце, приведен выше.

BOOL WINAPI CreateFtpDir( HWND hDlg, HINTERNET hConnection,
                          int nDirNameId, int nListBoxId )
{
  TCHAR szNewDirName[FTP_FUNCTIONS_BUFFER_SIZE];

  if( !GetDlgItemText( hDlg, nDirNameId, 
                       szNewDirName, 
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg, 
                TEXT( "Error: Directory Name Must Be Specified" ),
                TEXT( "Create FTP Directory" ), 
                MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  if( !FtpCreateDirectory( hConnection, szNewDirName ) )
  {
    InternetErrorOut( hDlg, GetLastError( ), 
                      TEXT( "FtpCreateDirectory" ) );
    return( FALSE );
  }

  return( DisplayFtpDir( hDlg, hConnection, 
                         INTERNET_FLAG_RELOAD, 
                         nListBoxId ) );
}

В следующем примере каталог удаляется с FTP-сервера. Имя удаляемого каталога берется из поля редактирования в родительском диалоговом окне, idC которого передается в параметр nDirNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP. Исходный код функции DisplayFtpDir, вызываемой в конце, приведен выше.

BOOL WINAPI RemoveFtpDir( HWND hDlg, HINTERNET hConnection,
                          int nDirNameId, int nListBoxId )
{
  TCHAR szDelDirName[FTP_FUNCTIONS_BUFFER_SIZE];

  if( !GetDlgItemText( hDlg, nDirNameId, szDelDirName, 
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg, 
                TEXT( "Error: Directory Name Must Be Specified" ),
                TEXT( "Remove FTP Directory" ), 
                MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  if( !FtpRemoveDirectory( hConnection, szDelDirName ) )
  {
    InternetErrorOut( hDlg, GetLastError( ), 
                      TEXT( "FtpRemoveDirectory" ) );
    return( FALSE );
  }

  return( DisplayFtpDir( hDlg, hConnection, 
                         INTERNET_FLAG_RELOAD, nListBoxId ) );
}

Получение файлов на FTP-сервере

Существует три способа получения файлов с FTP-сервера:

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

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

Если приложение установило дескриптор сеанса FTP на сервере с InternetConnect, приложение может вызвать FtpOpenFile с существующим именем файла и с новым именем для локально хранящегося файла. Затем приложение может скачать файл с помощью InternetReadFile . Это позволяет приложению более жестко контролировать скачивание и поддерживать подключение к FTP-серверу, что позволяет выполнять больше команд.

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

В следующем примере файл извлекается с FTP-сервера и сохраняется локально. Имя файла на FTP-сервере берется из поля редактирования в родительском диалоговом окне, idC которого передается в параметре nFtpFileNameId , а локальное имя, под которым сохраняется файл, берется из поля редактирования, IDC которого передается в параметре nLocalFileNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP.

BOOL WINAPI GetFtpFile( HWND hDlg, HINTERNET hConnection,
                        int nFtpFileNameId, int nLocalFileNameId )
{
  TCHAR szFtpFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szLocalFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  DWORD dwTransferType;
  TCHAR szBoxTitle[] = TEXT( "Download FTP File" );
  TCHAR szAsciiQuery[] =
    TEXT("Do you want to download as ASCII text?(Default is binary)");
  TCHAR szAsciiDone[] = 
    TEXT( "ASCII Transfer completed successfully..." );
  TCHAR szBinaryDone[] = 
    TEXT( "Binary Transfer completed successfully..." );

  if( !GetDlgItemText( hDlg, nFtpFileNameId, szFtpFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) ||
      !GetDlgItemText( hDlg, nLocalFileNameId, szLocalFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg, 
                TEXT( "Target File or Destination File Missing" ),
                szBoxTitle, 
                MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  dwTransferType = ( MessageBox( hDlg, 
                                 szAsciiQuery, 
                                 szBoxTitle, 
                                 MB_YESNO ) == IDYES ) ?
                   FTP_TRANSFER_TYPE_ASCII : FTP_TRANSFER_TYPE_BINARY;
  dwTransferType |= INTERNET_FLAG_RELOAD;

  if( !FtpGetFile( hConnection, szFtpFileName, szLocalFileName, FALSE,
                   FILE_ATTRIBUTE_NORMAL, dwTransferType, 0 ) )
  {
    InternetErrorOut( hDlg, GetLastError( ), TEXT( "FtpGetFile" ) );
    return( FALSE );
  }

  MessageBox( hDlg,( dwTransferType == 
                      (FTP_TRANSFER_TYPE_ASCII | INTERNET_FLAG_RELOAD)) ?
                      szAsciiDone : szBinaryDone, szBoxTitle, MB_OK );
  return( TRUE );
}

Размещение файлов на FTP-сервере

Существует два способа размещения файла на FTP-сервере.

Приложение, которое должно отправлять данные на FTP-сервер, но не имеет локального файла, содержащего все данные, должно использовать FtpOpenFile для создания и открытия файла на FTP-сервере. Затем приложение может использовать InternetWriteFile для отправки сведений в файл.

Если файл уже существует локально, приложение может использовать FtpPutFile для отправки файла на FTP-сервер. FtpPutFile выполняет все издержки, которые связаны с отправкой локального файла на удаленный FTP-сервер.

В следующем примере локальный файл копируется на FTP-сервер. Локальное имя файла берется из поля редактирования в родительском диалоговом окне, idC которого передается в параметре nLocalFileNameId , а имя, под которым файл сохраняется на FTP-сервере, берется из поля ввода, IDC которого передается в параметре nFtpFileNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP.

BOOL WINAPI PutFtpFile( HWND hDlg, HINTERNET hConnection,
                        int nFtpFileNameId, int nLocalFileNameId )
{
  TCHAR szFtpFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szLocalFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  DWORD dwTransferType;
  TCHAR szBoxTitle[] = TEXT( "Upload FTP File" );
  TCHAR szASCIIQuery[] =
    TEXT("Do you want to upload as ASCII text? (Default is binary)");
  TCHAR szAsciiDone[] = 
    TEXT( "ASCII Transfer completed successfully..." );
  TCHAR szBinaryDone[] = 
    TEXT( "Binary Transfer completed successfully..." );

  if( !GetDlgItemText( hDlg, nFtpFileNameId, szFtpFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) ||
      !GetDlgItemText( hDlg, nLocalFileNameId, szLocalFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg, 
                TEXT("Target File or Destination File Missing"),
                szBoxTitle, 
                MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  dwTransferType =
    ( MessageBox( hDlg, 
                  szASCIIQuery, 
                  szBoxTitle, 
                  MB_YESNO ) == IDYES ) ?
    FTP_TRANSFER_TYPE_ASCII : FTP_TRANSFER_TYPE_BINARY;

  if( !FtpPutFile( hConnection, 
                   szLocalFileName, 
                   szFtpFileName, 
                   dwTransferType, 
                   0 ) )
  {
    InternetErrorOut( hDlg, GetLastError( ), TEXT( "FtpGetFile" ) );
    return( FALSE );
  }

  MessageBox( hDlg,
              ( dwTransferType == FTP_TRANSFER_TYPE_ASCII ) ?
                szAsciiDone : szBinaryDone, szBoxTitle, MB_OK );
  return( TRUE );  // Remember to refresh directory listing
}

Удаление файлов с FTP-сервера

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

В следующем примере файл удаляется с FTP-сервера. Имя удаляемого файла берется из поля редактирования в родительском диалоговом окне, idC которого передается в параметре nFtpFileNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP. Так как эта функция не обновляет списки файлов или отображение каталогов, вызывающий процесс должен сделать это после успешного удаления.

BOOL WINAPI DeleteFtpFile( HWND hDlg, HINTERNET hConnection,
                           int nFtpFileNameId )
{
  TCHAR szFtpFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szBoxTitle[] = TEXT( "Delete FTP File" );

  if( !GetDlgItemText( hDlg, nFtpFileNameId, szFtpFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg, TEXT( "File Name Must Be Specified!" ),
                szBoxTitle, MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  if( !FtpDeleteFile( hConnection, szFtpFileName ) )
  {
    InternetErrorOut( hDlg, 
                      GetLastError( ), 
                      TEXT( "FtpDeleteFile" ) );
    return( FALSE );
  }

  MessageBox( hDlg, 
              TEXT( "File has been deleted" ), 
              szBoxTitle, 
              MB_OK );
  return( TRUE );  // Remember to refresh directory listing
}

Переименование файлов и каталогов на FTP-сервере

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

В следующем примере файл или каталог на FTP-сервере переименовывается. Текущее имя файла или каталога берется из поля редактирования в родительском диалоговом окне, idC которого передается в параметре nOldFileNameId , а новое имя берется из поля ввода, idC которого передается в параметре nNewFileNameId . Дескриптор hConnect был создан InternetConnect после установки сеанса FTP. Так как эта функция не обновляет списки файлов или отображение каталогов, вызывающий процесс должен делать это при успешном переименовании.

BOOL WINAPI RenameFtpFile( HWND hDlg, HINTERNET hConnection,
                           int nOldFileNameId, int nNewFileNameId )
{
  TCHAR szOldFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szNewFileName[FTP_FUNCTIONS_BUFFER_SIZE];
  TCHAR szBoxTitle[] = TEXT( "Rename FTP File" );

  if( !GetDlgItemText( hDlg, nOldFileNameId, szOldFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) ||
      !GetDlgItemText( hDlg, nNewFileNameId, szNewFileName,
                       FTP_FUNCTIONS_BUFFER_SIZE ) )
  {
    MessageBox( hDlg,
        TEXT( "Both the current and new file names must be supplied" ),
        szBoxTitle, 
        MB_OK | MB_ICONERROR );
    return( FALSE );
  }

  if( !FtpRenameFile( hConnection, szOldFileName, szNewFileName ) )
  {
    MessageBox( hDlg,
        TEXT( "FtpRenameFile failed" ),
        szBoxTitle, 
        MB_OK | MB_ICONERROR );
    return( FALSE );
  }
  return( TRUE );  // Remember to refresh directory listing
}

Примечание

WinINet не поддерживает реализации сервера. Кроме того, его не следует использовать из службы. Для серверных реализаций или служб используйте службы Microsoft Windows HTTP (WinHTTP).