Поделиться через


Сеансы 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 Handles.

Использование функций 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 использует "анонимный" для имени пользователя и адрес электронной почты пользователя для пароля. Если задан только пароль 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 — это дескриптор, возвращаемый функциейInternetConnectInternetConnect после создания сеанса 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. Новое имя каталога берется из поля редактирования родительского диалогового окна, идентификатор которого передается в параметре 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-terminated, которая содержит полный путь или имя относительно текущего каталога и создает каталог на 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" и каталог с именем "example" в каталоге test.

/* 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-сервере. Новое имя каталога берется из поля редактирования родительского диалогового окна, идентификатор которого передается в параметре nDirNameId. Дескриптор hConnection был создан 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-сервера. Имя удаленного каталога берется из поля редактирования в родительском диалоговом окне, идентификатор которого передается в параметр nDirNameId. Дескриптор hConnection был создан 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 для подключения к данному URL-адресу, а затем использовать InternetReadFile для управления загрузкой файла. Это позволяет приложению более жестко контролировать скачивание и идеально подходит для ситуаций, когда другие операции не должны выполняться на FTP-сервере. Дополнительные сведения о том, как напрямую получить доступ к ресурсам, см. в статье доступ к URL-адресам напрямую.

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

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

В следующем примере извлекается файл с FTP-сервера и сохраняется локально. Имя файла на FTP-сервере берется из поля редактирования в родительском диалоговом окне, идентификатор которого передается в параметре nFtpFileNameId, а локальное имя, под которым сохраняется файл, берется из поля редактирования, идентификатор которого передается в параметре nLocalFileNameId. Дескриптор hConnection был создан 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-сервер. Локальное имя файла берется из поля редактирования в родительском диалоговом окне, идентификатор которого передается в параметре nLocalFileNameId, и имя, под которым файл сохраняется на FTP-сервере, берется из поля редактирования, идентификатор которого передается в параметре nFtpFileNameId. Дескриптор hConnection был создан 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-сервера. Имя удаленного файла берется из поля редактирования в родительском диалоговом окне, идентификатор которого передается в параметре nFtpFileNameId. Дескриптор hConnection был создан 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-сервере переименовывается. Текущее имя файла или каталога берется из поля редактирования в родительском диалоговом окне, идентификатор которого передается в параметре nOldFileNameId, а новое имя берется из поля редактирования, идентификатор которого передается в параметре nNewFileNameId. Дескриптор hConnection был создан 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 Services (WinHTTP).