首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 實作 FTP 客戶端完整指南:CInternetSession 與 CFtpConnection 核心類別詳解

     編輯:關於C語言

MFC 網際網路類別架構:三層封裝

MFC 自 VC6 起提供 WinInet 封裝類別,位於 afxinet.h,三層架構:

層級類別職責
會話管理CInternetSession初始化 WinInet、設定代理/逾時/回呼、建立連線
協議連線CFtpConnection、CHttpConnection、CGopherConnection特定協議命令 (FTP: DIR, GET, PUT; HTTP: GET, POST)
檔案/資料流CInternetFile (繼承 CStdioFile → CFile)讀寫遠端檔案、支援 Seek、Text/Binary 模式

四步驟完成 FTP 基本操作

#include   // 需在 stdafx.h 或專案包含
#pragma comment(lib, "wininet.lib") // 連結 WinInet

void CFtpSampleDlg::OnDownload()
{
    // 1. 建立網際網路會話
    CInternetSession session(_T("MyFtpClient/1.0"), 1, PRE_CONFIG_INTERNET_ACCESS);
    session.SetOption(INTERNET_OPTION_CONNECT_TIMEOUT, 10000); // 10 秒連線逾時
    session.SetOption(INTERNET_OPTION_CONTROL_SEND_TIMEOUT, 5000);
    session.SetOption(INTERNET_OPTION_CONTROL_RECEIVE_TIMEOUT, 5000);

    // 2. 開啟 FTP 連線
    CFtpConnection* pFtp = session.GetFtpConnection(
        _T("ftp.microsoft.com"),   // 伺服器
        _T("anonymous"),           // 使用者
        _T("user@domain.com"),     // 密碼 (匿名用 email)
        21,                        // 埠號
        FALSE                      // TRUE = 被動模式 (預設 TRUE,穿透防火牆較好)
    );
    if (!pFtp) { AfxMessageBox(_T("連線失敗")); return; }

    // 3. 開啟遠端檔案 (唯讀)
    CInternetFile* pFile = pFtp->OpenFile(_T("/pub/file.txt"), GENERIC_READ, FTP_TRANSFER_TYPE_ASCII);
    if (!pFile) { AfxMessageBox(_T("開啟檔案失敗")); pFtp->Close(); delete pFtp; return; }

    // 4. 讀取內容 (繼承 CStdioFile,可用 ReadString)
    CString strLine, strAll;
    while (pFile->ReadString(strLine)) {
        strAll += strLine + _T("\r\n");
    }
    m_editLog.SetWindowText(strAll); // 顯示到 UI

    // 清理 (逆序)
    pFile->Close(); delete pFile;
    pFtp->Close(); delete pFtp;
    session.Close();
}

高階便利函數:一行代碼上傳/下載


// 下載整個檔案 (斷點續傳需自行實作)
BOOL success = pFtp->GetFile(
    _T("/remote/path/file.zip"),   // 遠端路徑
    _T("C:\\local\\file.zip"),     // 本地路徑
    FALSE,                         // TRUE = 失敗時刪除本地檔
    FILE_ATTRIBUTE_NORMAL,         // 本地屬性
    FTP_TRANSFER_TYPE_BINARY,      // 二進位模式 (關鍵!)
    0                              // 內容位移 (0 = 從頭)
);

// 上傳整個檔案
success = pFtp->PutFile(
    _T("C:\\local\\report.pdf"),
    _T("/upload/report.pdf"),
    FTP_TRANSFER_TYPE_BINARY,
    0
);

注意:FTP_TRANSFER_TYPE_ASCII 會轉換換行符 (CRLF↔LF),二進位檔案必須用 BINARY。

進階功能實作

1. 列出目錄內容 (CFtpFileFind)


CFtpFileFind finder(pFtp);
BOOL bFound = finder.FindFile(_T("*.*")); // 根目錄
while (bFound) {
    bFound = finder.FindNextFile();
    if (finder.IsDots()) continue;
    CString name = finder.GetFileName();
    BOOL isDir = finder.IsDirectory();
    ULONGLONG size = finder.GetLength();
    FILETIME ft; finder.GetLastWriteTime(&ft);
    // 加入 ListCtrl 或 TreeCtrl
}
finder.Close();

2. 斷點續傳 (Seek + 例外處理)


CInternetFile* pFile = pFtp->OpenFile(_T("/big.iso"), GENERIC_READ, FTP_TRANSFER_TYPE_BINARY);
if (pFile) {
    try {
        // 已下載 100MB,從此處續傳
        pFile->Seek(100 * 1024 * 1024, CFile::begin);
        // 繼續讀取...
    } catch (CInternetException* e) {
        // 伺服器不支援 REST 指令 → 例外
        e->Delete();
        // 落回重新下載
    }
}

3. 目錄操作


pFtp->CreateDirectory(_T("new_folder"));
pFtp->RemoveDirectory(_T("empty_folder"));
pFtp->SetCurrentDirectory(_T("subdir"));
pFtp->Rename(_T("old.txt"), _T("new.txt"));
pFtp->DeleteFile(_T("obsolete.log"));

錯誤處理與例外機制


try {
    // 所有 FTP 操作
}
catch (CInternetException* pEx) {
    TCHAR szErr[256];
    pEx->GetErrorMessage(szErr, 255);
    AfxMessageBox(szErr);
    pEx->Delete(); // 必須 Delete!MFC 例外物件在堆疊上
}
catch (CMemoryException* pEx) {
    AfxMessageBox(_T("記憶體不足"));
    pEx->Delete();
}

常見 WinInet 錯誤碼:ERROR_INTERNET_TIMEOUT、ERROR_INTERNET_NAME_NOT_RESOLVED、ERROR_FTP_TRANSFER_IN_PROGRESS。

HTTP 同樣適用:CHttpConnection


CHttpConnection* pHttp = session.GetHttpConnection(_T("api.example.com"), 80);
CHttpFile* pFile = pHttp->OpenRequest(CHttpConnection::HTTP_VERB_GET, _T("/data.json"));
pFile->AddRequestHeaders(_T("Accept: application/json"));
pFile->SendRequest();
DWORD dwStatus; pFile->QueryInfoStatusCode(dwStatus); // 200, 404...
CString json; pFile->ReadString(json); // 讀取回應

部署與相依性

  • 目標機需安裝 WinInet (IE 3.0+ 內建,Windows 98/NT4 以上皆有)。
  • 專案連結 wininet.lib (已在預設庫清單)。
  • 若使用 MFC 共享 DLL,確保目標機有對應版本 mfcxxx.dll。

總結

MFC CInternetSession/CFtpConnection/CInternetFile 三層封裝,將複雜的 WinInet API 簡化為直觀的 C++ 介面。掌握會話配置、連線模式 (主動/被動)、傳輸類型 (ASCII/BINARY)、例外處理、斷點續傳原理,即可快速開發健壯的 FTP/HTTP 客戶端功能。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved