天天看點

wininet實作ftp用戶端關于傳輸進度的分析

wininet提供了接口FtpGetFile實作從ftp伺服器下載下傳檔案;提供了接口FtpPutFile實作把檔案上傳到ftp伺服器上。通過這兩個接口,我們能夠完成基本的ftp檔案傳輸用戶端功能。但是在傳輸的同時,我們希望知道目前大概傳輸了多少,傳輸完整個檔案大概需要多長時間,目前進度是多少,大概還有多長時間才能傳輸完畢。

單純依靠這兩個接口,我們無法實作這個功能。仔細翻閱msdn,發現wininet還提供了這樣一個接口:InternetSetStatusCallback。該函數就是設定檔案傳輸的回調函數,其原型如下:

 INTERNET_STATUS_CALLBACK              InternetSetStatusCallback(           
 HINTERNET                 hInternet         ,           
 INTERNET_STATUS_CALLBACK                 lpfnInternetCallback          
 );           

該接口為internet會話設定一個狀态回調函數:lpfnInternetCallback,該回調函數的原型聲明如下:

 void CALLBACK              InternetStatusCallback(           
 HINTERNET                 hInternet         ,           
 DWORD_PTR                 dwContext         ,           
 DWORD                 dwInternetStatus         ,           
 LPVOID                 lpvStatusInformation         ,           
 DWORD                 dwStatusInformationLength          
 );           

通過這個回調函數,我們可以實作對目前傳輸進度的控制:可以統計出到目前已經傳輸了多少位元組,并且計算出傳輸速率,進而可以得知大概還剩下多少時間。

下面這個類就是實作對ftp檔案傳輸用戶端的封裝:

//

// 子產品名稱:檔案傳輸狀态控制

// 子產品功能:實作對界面時時報告目前檔案傳輸的進度狀态,并且實作上傳和下載下傳

//             檔案的用戶端功能。

// 檔案名稱:ftpclientctrl.h

//________________________________________________________________________

#ifndef _WININET_

#include <wininet.h>

#endif

class CFtpClientCtrl 

{

public:

CFtpClientCtrl();

virtual ~CFtpClientCtrl();

enum

{

        ftp_begin,              // 對于該事件,wparam = ftp_begin,lparam表示要傳輸的檔案大小

        ftp_transfer,    // 對于該事件,wparam = ftp_transfer,lParam表示已經傳輸的大小

        ftp_end                 // 對于該事件,wparam = ftp_end,lparam表示結果,0--失敗,1--成功

};

// 設定ftp伺服器的連接配接參數

BOOL     SetServerParam(    LPCTSTR lpszIpAddr,   // IP位址

                                           LPCTSTR lpszUser,      // 登入名稱

                                           LPCTSTR lpszPwd,      // 登入密碼

                                           WORD    wPort = INTERNET_DEFAULT_FTP_PORT,     // FTP伺服器端口

                                           LPCTSTR lpszProxyName = NULL,    // 代理名稱

                                           LPCTSTR lpszProxyPwd = NULL);     // 代理密碼

// 開始下載下傳檔案

BOOL     BeginDownload(     HWND hWnd,                     // 接收消息的視窗

                                           LPCTSTR lpszRemote,  // 遠端檔案名稱

                                           LPCTSTR lpszLocal,     // 儲存本地的檔案

                                           DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

BOOL     BeginDownload(     DWORD dwThread,                    // 接收消息的線程

                                           LPCTSTR lpszRemote,  // 遠端檔案名稱

                                           LPCTSTR lpszLocal,     // 儲存本地的檔案

                                           DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

// 開始上傳檔案

BOOL     BeginUpload(  HWND hWnd,                     // 接收消息的視窗

                                           LPCTSTR lpszRemote,  // 遠端檔案名稱

                                           LPCTSTR lpszLocal,     // 本地檔案名稱

                                           DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

BOOL     BeginUpload(  DWORD dwThread,                    // 接收消息的線程

                                           LPCTSTR lpszRemote,  // 遠端檔案名稱

                                           LPCTSTR lpszLocal,     // 本地檔案名稱

                                           DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

// 結束傳輸檔案

BOOL     EndFtpFile();

// 得到目前ftp的會話句柄

HINTERNET  GetCurrentSession() const{return m_hSession;}

// 得到目前的連接配接句柄

HINTERNET  GetCurrentConnect() const{return m_hConnect;}

// 擷取遠端檔案名稱

LPCTSTR             GetCurrentRemoteFile() const{return m_szRemote;}

// 擷取本地檔案名稱

LPCTSTR             GetCurrentLocalFile() const{return m_szLocal;}

// 擷取目前傳輸的檔案類型

DWORD        GetCurrentFileType() const{return m_dwFileType;}

// 擷取目前傳輸接收消息視窗

HWND           GetCurrentFtpWnd() const{return m_hWnd;}

// 擷取目前傳輸接收消息線程

DWORD        GetCurrentFtpThread() const{return m_dwThread;}

// 擷取目前已經傳輸的大小

DWORD        GetCurrentFtpSize() const{return m_dwCurrentFtpSize;}

// 遞增已經傳輸的大小

DWORD        IncreaseFtpSize(DWORD dwStep);

// 注冊一個消息

void        RegisterMsgHandle(UINT uMsgHandle){m_uMsgHandle = uMsgHandle;}

// 擷取已經注冊的消息

UINT             GetRegisterMsgHandle() const{return m_uMsgHandle;}

// 擷取檔案總長度

DWORD        GetTotalFileSize() const{return m_dwTotalFileSize;}

// 清除FTP

void        ClearFtpSession();

// 設定FTP傳輸方向

void        SetFtpDirect(BOOL bDownload = TRUE){m_bFtpDirect = bDownload;}

// 擷取FTP傳輸方向

BOOL            GetFtpDirect() const{return m_bFtpDirect;}

// 判斷檔案類型是否是ASCII

static BOOL           IsFileAscii(LPCTSTR lpszFile);

protected:

// 擷取遠端檔案的大小

DWORD GetRemoteFileSize();

// 擷取本地檔案的大小

DWORD GetLocalFileSize();

// 下載下傳檔案

BOOL     DownloadFile(       LPCTSTR lpszRemote,  // 遠端檔案名稱

                                           LPCTSTR lpszLocal,     // 儲存本地的檔案

                                           DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

// 上傳檔案

BOOL     UploadFile(     LPCTSTR lpszRemote,  // 遠端檔案名稱

                                    LPCTSTR lpszLocal,     // 儲存本地的檔案

                                    DWORD dwFileType = FTP_TRANSFER_TYPE_UNKNOWN);      // 檔案傳輸

protected:

HINTERNET  m_hSession;          // 應用于InternetOpen

HINTERNET  m_hConnect;         // 應用于InternetConnect

TCHAR          m_szFtpSrvIp[24]; // FTP伺服器的ip位址

TCHAR          m_szFtpSrvUser[32];    // FTP伺服器的登入使用者

TCHAR          m_szFtpSrvPwd[32];    // FTP伺服器的登入密碼

TCHAR          m_szProxyName[64];    // 代理的名稱

TCHAR          m_szProxyPwd[32];             // 代理的密碼

WORD           m_wFtpSrvPort;           // FTP伺服器的監聽端口

HANDLE        m_hFtpThread;             // FTP傳輸的線程句柄

DWORD        m_dwFtpThread;          // FTP傳輸的線程編号

TCHAR          m_szRemote[MAX_PATH];          // 遠端檔案

TCHAR          m_szLocal[MAX_PATH];             // 本地檔案

DWORD        m_dwFileType;             // 傳輸的檔案類型

HWND           m_hWnd;                     // 接收傳輸進度消息的視窗

DWORD        m_dwThread;        // 接收傳輸進度消息的線程

DWORD        m_dwCurrentFtpSize;    // 目前傳輸的大小

DWORD        m_dwTotalFileSize;       // 檔案總大小

UINT             m_uMsgHandle;     // 消息句柄,由外界定義

BOOL            m_bFtpDirect;       // 傳輸方向,TRUE為下載下傳,FALSE為上傳,預設為TRUE

public:

DWORD        m_dwFtpHead;      // FTP傳輸頭--自從InternetConnect之後發送的次數

private:

BOOL            m_bTransfering;    // 是否正在傳輸

};

//

// 子產品名稱:檔案傳輸狀态控制

// 子產品功能:實作對界面時時報告目前檔案傳輸的進度狀态,并且實作上傳和下載下傳

//             檔案的用戶端功能。

// 檔案名稱:ftpclientctrl.cpp

//________________________________________________________________________

#include "FtpClientCtrl.h"

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

#define INTERNET_STATUS_USER_INPUT_REQUIRED         0x00000040

#define INTERNET_STATUS_DETECTING_PROXY               80

#define FTP_FILE_ASCII_COUNT      12

LPCTSTR g_lpszAsciiFileFtp[FTP_FILE_ASCII_COUNT] =

{

_T(".txt"),

_T(".ini"),

_T(".c"),

_T(".cpp"),

_T(".h"),

_T(".hpp"),

_T(".bat"),

_T(".html"),

_T(".java"),

_T(".htm"),

_T(".jav"),

_T(".doc")

};

//

// 名稱:IsFtpAscii

// 描述:經驗判斷一個要進行檔案傳輸的檔案是否是ASCII方式的

// 原型:BOOL IsFtpAscii(LPCTSTR lpszExt)    // 檔案字尾

// 參數:

//             [in] lpszExt:要判斷的檔案的字尾名稱

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL IsFtpAscii(LPCTSTR lpszExt)

{

if(lpszExt == NULL)

        return FALSE;

for(int nIndex = 0; nIndex < FTP_FILE_ASCII_COUNT; nIndex ++)

{

        if(_tcsicmp(lpszExt, g_lpszAsciiFileFtp[nIndex]) == 0)

               return TRUE;

}

return FALSE;

}// End IsFtpAscii

// IsFtpAscii結束

//

//

// 名稱:FormatFtpError

// 描述:擷取系統的錯誤描述

// 原型:void FormatFtpError(DWORD dwError,      // 錯誤碼

//                                                LPTSTR *lpMsg)   // 描述資訊

// 參數:

//             [in] dwError:要查詢的系統錯誤碼

//             [out] *lpMsg:擷取得到的錯誤描述資訊,在使用結束後,請調用LocalFree

//                                  來釋放該空間

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

static void FormatFtpError(    DWORD dwError,        // 系統錯誤碼

                                                  LPTSTR *lpMsg)   // 錯誤描述

{

if(lpMsg == NULL)return;

if(dwError > INTERNET_ERROR_BASE)

{

        // 對于Internet的錯誤,要特殊處理

        DWORD dwBufLen = 0;

        InternetGetLastResponseInfo(&dwError, NULL, &dwBufLen);

        LPTSTR pMsg = (LPTSTR)LocalAlloc(LMEM_ZEROINIT, dwBufLen + 1);

        InternetGetLastResponseInfo(&dwError, pMsg, &dwBufLen);

        *lpMsg = pMsg;

}

else

{

        // 查詢普通的錯誤

        FormatMessage(    FORMAT_MESSAGE_ALLOCATE_BUFFER |

                                    FORMAT_MESSAGE_IGNORE_INSERTS |

                                   FORMAT_MESSAGE_FROM_SYSTEM,

                                    NULL,

                                    dwError,

                                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

                                    (LPSTR)lpMsg,

                                    0,

                                    NULL);

}

}// End FormatFtpError

// FormatFtpError結束

//

//

// 名稱:FtpCtrl_CallbackStatus

// 描述:檔案傳輸過程中的狀态回調函數,用于報告目前檔案傳輸的進度等消息

// 原型:void CALLBACK FtpCtrl_CallbackStatus(     HINTERNET hInternet,// 句柄

//                                                                            DWORD dwContext, // 上下文

//                                                                            DWORD dwInternetStatus, // 狀态

//                                                                            LPVOID lpvStatusInformation,// 資訊

//                                                                            DWORD dwStatusInformationLength)

// 參數:

//             [in] hInternet:Internet連接配接的句柄,從InternetOpen中得到

//             [in] dwContext:自定義的上下文資料

//             [in] dwInternetStatus:目前回調的狀态

//             [in] lpvStatusInformation:目前回調的資訊,根據dwInternetStatus的不同

//                                         狀态代表不同的意思

//             [in] dwStatusInformationLength:回調資訊lpvStatusInformation的長度

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

void CALLBACK FtpCtrl_CallbackStatus(     HINTERNET hInternet,

                                                                DWORD dwContext,

                                                                DWORD dwInternetStatus,

                                                                LPVOID lpvStatusInformation,

                                                                DWORD dwStatusInformationLength)

{

// 擷取上下文資訊

CFtpClientCtrl *pcFtpMsg = reinterpret_cast<CFtpClientCtrl*>(dwContext);

if(pcFtpMsg == NULL)

{

        return;

}

LPDWORD pdwInformation(NULL);

TRACE("FtpCtrl_CallbackStatus's Internet Status is %d/n", dwInternetStatus);

// 查詢目前檔案傳輸狀态

switch(dwInternetStatus)

{

case INTERNET_STATUS_RESOLVING_NAME:      // 10

        TRACE("Looking up the IP address for %s/n", (LPCTSTR)lpvStatusInformation);

        break;

case INTERNET_STATUS_NAME_RESOLVED:        // 11

        TRACE("Name resolved %s/n", (LPCTSTR)lpvStatusInformation);

        break;

case INTERNET_STATUS_CONNECTING_TO_SERVER:       // 20

        // lpvStatusInformation是一個SOCKADDR的指針

        TRACE("Connecting to server--%s.../n", (LPCTSTR)lpvStatusInformation);

        break;

case INTERNET_STATUS_CONNECTED_TO_SERVER:  // 21

        // lpvStatusInformation是一個SOCKADDR的指針

        TRACE("Connected to server--%s/n", (LPCTSTR)lpvStatusInformation);

        break;

case INTERNET_STATUS_SENDING_REQUEST:           // 30

        TRACE("Sending request/n");

        break;

case INTERNET_STATUS_REQUEST_SENT:                  // 31

        {

               // 發送資料到伺服器

               if(!pcFtpMsg->GetFtpDirect())

               {

                      // 隻有當處于上傳狀态的時候,才處理

                      if(pcFtpMsg->m_dwFtpHead > 0 && pcFtpMsg->m_dwFtpHead < 5)

                      {

                             // 5這個值是一個經驗值,具體為什麼,由于沒有深入研究rfc的協定

                             // 是以還不知道,将來如果知道原因,可以補充上

                             pcFtpMsg->m_dwFtpHead ++;

                      }

                      pdwInformation = (LPDWORD)lpvStatusInformation;

                      if(pcFtpMsg->m_dwFtpHead == 5)

                      {

                             DWORD dwCurrentSize = pcFtpMsg->IncreaseFtpSize(*pdwInformation);

                             TRACE("本次發送的資料大小為: %d,總共資料為:%d/n", *pdwInformation,

                                    dwCurrentSize);

                             if(pcFtpMsg->GetCurrentFtpWnd() != NULL)

                             {

                                    // 首先的第一選擇是給視窗發送消息

                                    ::PostMessage(       pcFtpMsg->GetCurrentFtpWnd(),

                                                                pcFtpMsg->GetRegisterMsgHandle(),

                                                                CFtpClientCtrl::ftp_transfer,

                                                                dwCurrentSize);

                             }

                             else if(pcFtpMsg->GetCurrentFtpThread() != 0)

                             {

                                    ::PostThreadMessage(pcFtpMsg->GetCurrentFtpThread(),

                                                                       pcFtpMsg->GetRegisterMsgHandle(),

                                                                       CFtpClientCtrl::ftp_transfer,

                                                                       dwCurrentSize);

                             }

                      }// End if 5,經驗值

               }// end if 檔案上傳

        }

        break;

case INTERNET_STATUS_RESPONSE_RECEIVED:        // 41

        {

               // 從伺服器接收到的響應

               if(pcFtpMsg->GetFtpDirect())

               {

                      // 隻有當處于下載下傳狀态的時候,才處理

                      pdwInformation = (LPDWORD)lpvStatusInformation;

                      if(pcFtpMsg->m_dwFtpHead > 0 && pcFtpMsg->m_dwFtpHead < 6)

                      {

                             // 6這個值是一個經驗值,具體為什麼,由于沒有深入研究rfc的協定

                             // 是以還不知道,将來如果知道原因,可以補充上

                             pcFtpMsg->m_dwFtpHead ++;

//                                  TRACE("在連接配接之後第%d次接收資料!/n", pcFtpMsg->m_dwFtpHead);

                      }

                      if(pcFtpMsg->m_dwFtpHead == 6)

                      {

                             DWORD dwCurrentSize = pcFtpMsg->IncreaseFtpSize(*pdwInformation);

                             TRACE("Response received: %d, TotalReceived is %d/n",

                                    *pdwInformation, dwCurrentSize);

                             if(pcFtpMsg->GetCurrentFtpWnd() != NULL)

                             {

                                    ::PostMessage(       pcFtpMsg->GetCurrentFtpWnd(),

                                                                pcFtpMsg->GetRegisterMsgHandle(),

                                                                CFtpClientCtrl::ftp_transfer,

                                                                dwCurrentSize);

                             }

                             else if(pcFtpMsg->GetCurrentFtpThread() != 0)

                             {

                                    ::PostThreadMessage(pcFtpMsg->GetCurrentFtpThread(),

                                                                       pcFtpMsg->GetRegisterMsgHandle(),

                                                                       CFtpClientCtrl::ftp_transfer,

                                                                       dwCurrentSize);

                             }

                      }// End if 6,經驗值

               }// End if 檔案下載下傳

        }

        break;

case INTERNET_STATUS_RECEIVING_RESPONSE:             // 40

        // 等待伺服器的響應,lpvStatusInformation = NULL

        TRACE("等待伺服器的響應!/n");

        break;

case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:              // 42

case INTERNET_STATUS_PREFETCH:                                 // 43

case INTERNET_STATUS_CLOSING_CONNECTION:           // 50

        TRACE("Closing connection/n");

        break;

case INTERNET_STATUS_CONNECTION_CLOSED:                    // 51

        TRACE("Connection closed/n");

        break;

case INTERNET_STATUS_HANDLE_CREATED:                    // 60

        {

               LPINTERNET_ASYNC_RESULT ptIAR =

                      reinterpret_cast<LPINTERNET_ASYNC_RESULT>(lpvStatusInformation);

               if(hInternet == pcFtpMsg->GetCurrentConnect())

               {

                      TRACE("Connect Handle Created!/n");

                      pcFtpMsg->m_dwFtpHead = 1;

               }

               else if(hInternet == pcFtpMsg->GetCurrentSession())

               {

                      TRACE("Session handle created!/n");

               }

        }

        break;

case INTERNET_STATUS_HANDLE_CLOSING:                    // 70

        pcFtpMsg->m_dwFtpHead = 0;

        TRACE("Handle closed with dif %d!/n",

               pcFtpMsg->GetCurrentFtpSize() - pcFtpMsg->GetTotalFileSize());

        break;

case INTERNET_STATUS_DETECTING_PROXY:                  // 80

        TRACE("Detecting proxy/n");

        break;

case INTERNET_STATUS_REQUEST_COMPLETE:               // 100

        // 一個異步操作已經完成,lpvStatusInformation是INTERNET_ASYNC_RESULT的指針

        {

               LPINTERNET_ASYNC_RESULT ptIAR =

                      reinterpret_cast<LPINTERNET_ASYNC_RESULT>(lpvStatusInformation);

               TRACE("一個異步操作完成,錯誤為:%d,結果為:%d/n",

                      ptIAR->dwError, ptIAR->dwResult);

        }

        break;

case INTERNET_STATUS_REDIRECT:                                  // 110

        TRACE("HTTP request redirected to /n");

        break;

case INTERNET_STATUS_INTERMEDIATE_RESPONSE:             // 120

        TRACE("Received intermediate status message from the server./n");

        break;

case INTERNET_STATUS_STATE_CHANGE:                         // 200

        TRACE("'Moved between a secure and a nonsecure site/n");

        {

               LPDWORD pdwRead = (LPDWORD)lpvStatusInformation;

               switch(*pdwRead)

               {

               case INTERNET_STATE_CONNECTED:                  // 0x00000001

                      TRACE("Connected state moved between secure and nonsecure site/n");

                      break;

               case INTERNET_STATE_DISCONNECTED:            // 0x00000002

                      TRACE("Disconnected from network/n");

                      break;

               case INTERNET_STATE_DISCONNECTED_BY_USER:   // 0x00000010

                      TRACE("Disconnected by user request/n");

                      break;

               case INTERNET_STATE_IDLE:                        // 0x00000100

                      TRACE("No network requests are being made (by Wininet)./n");

                      break;

               case INTERNET_STATE_BUSY:                       // 0x00000200

                      TRACE("Network requests are being made (by Wininet)./n");

                      break;

               case INTERNET_STATUS_USER_INPUT_REQUIRED:    // 0x00000040

                      TRACE("The request requires user input to complete/n");

                      break;

               default:

                      break;

               }

        }

        break;

default:

        break;

}

}// End Ftp_CallbackStatus

// Ftp_CallbackStatu結束

//

//

// 名稱:FtpClientDnloadThread

// 描述:檔案傳輸——下載下傳用戶端線程

// 原型:DWORD WINPAI FtpClientDnloadThread(LPVOID pParam)     // 入口參數

// 參數:

//             [in] pParam:下載下傳檔案的入口參數

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

DWORD WINAPI FtpClientDnloadThread(LPVOID pParam)     // 入口參數

{

CFtpClientCtrl *pcFtpMsg = reinterpret_cast<CFtpClientCtrl*>(pParam);

if(pcFtpMsg == NULL)

{

        return -1;

}

// 擷取檔案

BOOL bRet = FtpGetFile(      pcFtpMsg->GetCurrentConnect(),

                                           pcFtpMsg->GetCurrentRemoteFile(),

                                           pcFtpMsg->GetCurrentLocalFile(),

                                           FALSE,

                                           FILE_ATTRIBUTE_NORMAL,

                                           pcFtpMsg->GetCurrentFileType() |

                                           INTERNET_FLAG_RELOAD |

                                           INTERNET_FLAG_RESYNCHRONIZE,

                                           (DWORD)pcFtpMsg);

LPTSTR lpMsg = NULL;

DWORD dwErr = GetLastError();

FormatFtpError(dwErr, &lpMsg);

TRACE("FtpGetFile Error with %d--%s/n", dwErr, lpMsg);

LocalFree(lpMsg);

lpMsg = NULL;

if(pcFtpMsg->GetCurrentFtpWnd() != NULL)

{

        ::PostMessage(       pcFtpMsg->GetCurrentFtpWnd(),

                                    pcFtpMsg->GetRegisterMsgHandle(),

                                    CFtpClientCtrl::ftp_end,

                                    dwErr);

}

else if(pcFtpMsg->GetCurrentFtpThread() != 0)

{

        ::PostThreadMessage(pcFtpMsg->GetCurrentFtpThread(),

                                           pcFtpMsg->GetRegisterMsgHandle(),

                                           CFtpClientCtrl::ftp_end,

                                           dwErr);

}

pcFtpMsg->ClearFtpSession();

TRACE("FtpGetFile Thread with id 0x%x end!/n", GetCurrentThreadId());

if(!bRet)

        return -1;

return 0;

}// End FtpClientDnloadThread

// FtpClientDnloadThread結束

//

//

// 名稱:FtpClientUploadThread

// 描述:檔案傳輸——上傳檔案線程

// 原型:DWORD WINAPI FtpClientUploadThread(LPVOID pParam)     // 入口參數

// 參數:

//             [in] pParam:上傳檔案需要的參數

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

DWORD WINAPI FtpClientUploadThread(LPVOID pParam)

{

CFtpClientCtrl *pcFtpMsg = reinterpret_cast<CFtpClientCtrl*>(pParam);

if(pcFtpMsg == NULL)

{

        return -1;

}

// 上傳檔案

BOOL bRet = FtpPutFile(      pcFtpMsg->GetCurrentConnect(),

                                           pcFtpMsg->GetCurrentLocalFile(),

                                           pcFtpMsg->GetCurrentRemoteFile(),

                                           pcFtpMsg->GetCurrentFileType() |

                                           INTERNET_FLAG_RESYNCHRONIZE,

                                           (DWORD)pcFtpMsg);

LPTSTR lpMsg = NULL;

DWORD dwErr = GetLastError();

FormatFtpError(dwErr, &lpMsg);

TRACE("FtpPutFile Error with %d--%s/n", dwErr, lpMsg);

LocalFree(lpMsg);

lpMsg = NULL;

if(pcFtpMsg->GetCurrentFtpWnd() != NULL)

{

        ::PostMessage(       pcFtpMsg->GetCurrentFtpWnd(),

                                    pcFtpMsg->GetRegisterMsgHandle(),

                                    CFtpClientCtrl::ftp_end,

                                    dwErr);

}

else if(pcFtpMsg->GetCurrentFtpThread() != 0)

{

        ::PostThreadMessage(pcFtpMsg->GetCurrentFtpThread(),

                                           pcFtpMsg->GetRegisterMsgHandle(),

                                           CFtpClientCtrl::ftp_end,

                                           dwErr);

}

pcFtpMsg->ClearFtpSession();

TRACE("FtpPutFile Thread with id 0x%x end!/n", GetCurrentThreadId());

if(!bRet)

{

        return -1;

}

return 0;

}// End FtpClientUploadThread

// FtpClientUploadThread結束

//

CFtpClientCtrl::CFtpClientCtrl()

               :m_wFtpSrvPort(INTERNET_DEFAULT_FTP_PORT)

               ,m_hSession(NULL)

               ,m_hConnect(NULL)

               ,m_hFtpThread(NULL)

               ,m_dwFtpThread(0)

               ,m_dwCurrentFtpSize(0)

               ,m_hWnd(NULL)

               ,m_dwFileType(FTP_TRANSFER_TYPE_UNKNOWN)

               ,m_uMsgHandle(0)

               ,m_bFtpDirect(TRUE)

               ,m_dwFtpHead(0)

               ,m_bTransfering(FALSE)

{

::ZeroMemory(m_szFtpSrvIp, 24);

::ZeroMemory(m_szFtpSrvPwd, 32);

::ZeroMemory(m_szFtpSrvUser, 32);

::ZeroMemory(m_szProxyName, 64);

::ZeroMemory(m_szProxyPwd, 32);

::ZeroMemory(m_szRemote, MAX_PATH);

::ZeroMemory(m_szLocal, MAX_PATH);

}

CFtpClientCtrl::~CFtpClientCtrl()

{

InternetCloseHandle(m_hConnect);

InternetCloseHandle(m_hSession);

}

//

// 名稱:SetServerParam

// 描述:設定檔案傳輸的FTP伺服器參數,包括伺服器的位址、端口、使用者和,密碼等

// 原型:BOOL SetServerParam(LPCTSTR lpszIpAddr,     // 伺服器位址

//                                                LPCTSTR lpszUser,             // 使用者

//                                                LPCTSTR lpszPwd,             // 密碼

//                                                WORD wPort,                     // 端口

//                                                LPCTSTR lpszProxyName,   // 代理名稱

//                                                LPCTSTR lpszProxyPwd)    // 代理密碼

// 參數:

//             [in] lpszIpAddr:FTP伺服器的位址

//             [in] lpszUser:FTP伺服器的使用者名稱

//             [in] lpszPwd:FTP伺服器的使用者密碼

//             [in] wPort:FTP伺服器的偵聽端口

//             [in] lpszProxyName:FTP伺服器的代理使用者

//             [in] lpszProxyPwd:FTP伺服器的代理對應密碼

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::SetServerParam(LPCTSTR lpszIpAddr,

                                                         LPCTSTR lpszUser,

                                                         LPCTSTR lpszPwd,

                                                         WORD wPort,

                                                         LPCTSTR lpszProxyName,

                                                         LPCTSTR lpszProxyPwd)

{

if(    lpszIpAddr == NULL ||

        lpszUser == NULL ||

        lpszPwd == NULL ||

        wPort == 0)

        return FALSE;

::ZeroMemory(m_szFtpSrvIp, 24);

_sntprintf(m_szFtpSrvIp, 24, _T("%s"), lpszIpAddr);

::ZeroMemory(m_szFtpSrvUser, 32);

_sntprintf(m_szFtpSrvUser, 32, _T("%s"), lpszUser);

::ZeroMemory(m_szFtpSrvPwd, 32);

_sntprintf(m_szFtpSrvPwd, 32, _T("%s"), lpszPwd);

m_wFtpSrvPort = wPort;

::ZeroMemory(m_szProxyName, 64);

_sntprintf(m_szProxyName, 64, _T("%s"), lpszProxyName);

::ZeroMemory(m_szProxyPwd, 32);

_sntprintf(m_szProxyPwd, 32, _T("%s"), lpszProxyPwd);

return TRUE;

}// End SetServerParam

// SetServerParam結束

//

//

// 名稱:DownloadFile

// 描述:下載下傳檔案

// 原型:BOOL DownloadFile(     LPCTSTR lpszRemote,  // 遠端檔案

//                                                LPCTSTR lpszLocal,     // 本地檔案

//                                                DWORD dwFileType)   // 檔案類型

// 參數:

//             [in] lpszRemote:要下載下傳的檔案名稱

//             [in] lpszLocal:檔案下載下傳後儲存到本地的路徑

//             [in] dwFileType:檔案傳輸的方式

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::DownloadFile(LPCTSTR lpszRemote,

                                                    LPCTSTR lpszLocal,

                                                    DWORD dwFileType)

{

::ZeroMemory(m_szRemote, MAX_PATH);

_sntprintf(m_szRemote, MAX_PATH, _T("%s"), lpszRemote);

::ZeroMemory(m_szLocal, MAX_PATH);

_sntprintf(m_szLocal, MAX_PATH, _T("%s"), lpszLocal);

m_dwFileType = dwFileType;

m_dwFtpHead = 0;

m_bFtpDirect = TRUE;

// 設定檔案傳輸方式

if(dwFileType == FTP_TRANSFER_TYPE_UNKNOWN)

{

        LPCTSTR lpszExt = _tcsrchr(lpszRemote, '.');

        if(IsFtpAscii(lpszExt))

               m_dwFileType = FTP_TRANSFER_TYPE_ASCII;

        else

               m_dwFileType = FTP_TRANSFER_TYPE_BINARY;

}

// 擷取遠端檔案的大小,有的時候不能成功

m_dwTotalFileSize = GetRemoteFileSize();

TRACE("Remote File size is %d/n", m_dwTotalFileSize);

m_dwCurrentFtpSize = 0;

LPTSTR lpMsg = NULL;      // 錯誤資訊

// 打開Internet連接配接

m_hSession = InternetOpen( _T("Ftp_Ctrl"),

                                                  INTERNET_OPEN_TYPE_DIRECT,

                                                  m_szProxyName,

                                                  m_szProxyPwd,

                                                  INTERNET_FLAG_NO_CACHE_WRITE);

if(m_hSession == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetOpen Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        lpMsg = NULL;

        return FALSE;

}

// 設定狀态回調函數

if(InternetSetStatusCallback(m_hSession, FtpCtrl_CallbackStatus) ==

        INTERNET_INVALID_STATUS_CALLBACK)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetSetStatusCallback Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        lpMsg = NULL;

        InternetCloseHandle(m_hSession);

        return FALSE;

}

// 連接配接到對方

m_hConnect = InternetConnect(   m_hSession,

                                                         m_szFtpSrvIp,

                                                         m_wFtpSrvPort,

                                                         m_szFtpSrvUser,

                                                         m_szFtpSrvPwd,

                                                         INTERNET_SERVICE_FTP,

                                                         INTERNET_FLAG_PASSIVE |

                                                         INTERNET_FLAG_EXISTING_CONNECT,

                                                         (DWORD)this);

if(m_hConnect == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetConnect Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        lpMsg = NULL;

        InternetCloseHandle(m_hSession);

        return FALSE;

}

if(m_hWnd != NULL)

{

        // 發送消息,開始下載下傳了

        ::PostMessage(       m_hWnd, m_uMsgHandle,

                                    (WPARAM)ftp_begin, (LPARAM)m_dwTotalFileSize);

}

else if(m_dwThread != 0)

{

        ::PostThreadMessage(m_dwThread, m_uMsgHandle,

                                           (WPARAM)ftp_begin, (LPARAM)m_dwTotalFileSize);

}

// 建立檔案下載下傳線程

m_hFtpThread = CreateThread(NULL,

                                                  0,

                                                  FtpClientDnloadThread,

                                                  this,

                                                  0,

                                                  &m_dwFtpThread);

if(m_hFtpThread == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("CreateThread Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        InternetCloseHandle(m_hConnect);

        InternetCloseHandle(m_hSession);

        return FALSE;

}

m_bTransfering = TRUE;

return TRUE;

}// End DownloadFile

// DownloadFile結束

//

//

// 名稱:BeginDownload

// 描述:開始下載下傳檔案

// 原型:BOOL BeginDownload(HWND hWnd,   // 接收消息的視窗

//                                                LPCTSTR lpszRemote,  // 遠端檔案

//                                                LPCTSTR lpszLocal,     // 本地檔案

//                                                DWORD dwFileType)   // 檔案類型

// 參數:

//             [in] hWnd:用于接收檔案傳輸狀态報告的視窗句柄

//             [in] lpszRemote:要下載下傳的檔案名稱,儲存在伺服器上的

//             [in] lpszLocal:檔案下載下傳後儲存到本地的路徑

//             [in] dwFileType:檔案傳輸的方式

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::BeginDownload(HWND hWnd,

                                                     LPCTSTR lpszRemote,

                                                     LPCTSTR lpszLocal,

                                                     DWORD dwFileType)

{

if(    lpszRemote == NULL ||

        lpszLocal == NULL ||

        (dwFileType != FTP_TRANSFER_TYPE_BINARY &&

        dwFileType != FTP_TRANSFER_TYPE_ASCII &&

        dwFileType != FTP_TRANSFER_TYPE_UNKNOWN) ||

        hWnd == NULL)

        return FALSE;

if(m_bTransfering)

        return FALSE;

m_hWnd = hWnd;

return DownloadFile(lpszRemote,

                                    lpszLocal,

                                    dwFileType);

}// End BeginDownload

// BeginDownload結束

//

//

// 名稱:BeginDownload

// 描述:開始下載下傳檔案

// 原型:BOOL BeginDownload(DWORD dwThread, // 接收消息的線程

//                                                LPCTSTR lpszRemote,  // 遠端檔案

//                                                LPCTSTR lpszLocal,     // 本地檔案

//                                                DWORD dwFileType)   // 檔案類型

// 參數:

//             [in] dwThread:用于接收檔案傳輸狀态報告的線程句柄

//             [in] lpszRemote:要下載下傳的檔案名稱,儲存在伺服器上的

//             [in] lpszLocal:檔案下載下傳後儲存到本地的路徑

//             [in] dwFileType:檔案傳輸的方式

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::BeginDownload(DWORD dwThread,

                                                     LPCTSTR lpszRemote,

                                                     LPCTSTR lpszLocal,

                                                     DWORD dwFileType)

{

if(    lpszRemote == NULL ||

        lpszLocal == NULL ||

        (dwFileType != FTP_TRANSFER_TYPE_BINARY &&

        dwFileType != FTP_TRANSFER_TYPE_ASCII &&

        dwFileType != FTP_TRANSFER_TYPE_UNKNOWN) ||

        dwThread == 0)

        return FALSE;

if(m_bTransfering)

        return FALSE;

m_dwThread = dwThread;

return DownloadFile(lpszRemote,

                                    lpszLocal,

                                    dwFileType);

}// End BeginDownload

// BeginDownload結束

//

//

// 名稱:UploadFile

// 描述:上傳檔案

// 原型:BOOL UploadFile(   LPCTSTR lpszRemote,  // 遠端檔案

//                                                LPCTSTR lpszLocal,     // 本地檔案

//                                                DWORD dwFileType)   // 檔案類型

// 參數:

//             [in] lpszRemote:上傳後儲存的檔案名稱

//             [in] lpszLocal:要上傳的本地檔案路徑

//             [in] dwFileType:檔案傳輸的方式

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::UploadFile(LPCTSTR lpszRemote,

                                                  LPCTSTR lpszLocal,

                                                  DWORD dwFileType)

{

m_dwFtpHead = 0;

m_bFtpDirect = FALSE;

::ZeroMemory(m_szRemote, MAX_PATH);

_sntprintf(m_szRemote, MAX_PATH, _T("%s"), lpszRemote);

::ZeroMemory(m_szLocal, MAX_PATH);

_sntprintf(m_szLocal, MAX_PATH, _T("%s"), lpszLocal);

m_dwFileType = dwFileType;

// 設定檔案傳輸的方式

if(dwFileType == FTP_TRANSFER_TYPE_UNKNOWN)

{

        LPCTSTR lpszExt = _tcsrchr(lpszLocal, '.');

        if(IsFtpAscii(lpszExt))

               m_dwFileType = FTP_TRANSFER_TYPE_ASCII;

        else

               m_dwFileType = FTP_TRANSFER_TYPE_BINARY;

}

// 計算本地檔案的大小,隻要該檔案存在,就能夠得到大小

m_dwTotalFileSize = GetLocalFileSize();

if(m_dwTotalFileSize == (DWORD)-1)

{

        m_dwTotalFileSize = 0;

        return FALSE;

}

TRACE("Local File size is %d/n", m_dwTotalFileSize);

m_dwCurrentFtpSize = 0;

LPTSTR lpMsg = NULL;      // 消息描述

// 打開Internet連接配接會話

m_hSession = InternetOpen( _T("Ftp_Ctrl"),

                                                 INTERNET_OPEN_TYPE_DIRECT,

                                                  m_szProxyName,

                                                  m_szProxyPwd,

                                                  INTERNET_FLAG_NO_CACHE_WRITE);

if(m_hSession == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetOpen Error with %s/n", lpMsg);

        LocalFree(lpMsg);

       lpMsg = NULL;

        return FALSE;

}

// 設定檔案傳輸狀态回調函數

if(InternetSetStatusCallback(m_hSession, FtpCtrl_CallbackStatus) ==

        INTERNET_INVALID_STATUS_CALLBACK)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetSetStatusCallback Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        lpMsg = NULL;

        InternetCloseHandle(m_hSession);

        return FALSE;

}

// 開始建立檔案傳輸的連接配接

m_hConnect = InternetConnect(   m_hSession,

                                                         m_szFtpSrvIp,

                                                         m_wFtpSrvPort,

                                                         m_szFtpSrvUser,

                                                         m_szFtpSrvPwd,

                                                        INTERNET_SERVICE_FTP,

                                                         INTERNET_FLAG_PASSIVE |

                                                         INTERNET_FLAG_EXISTING_CONNECT,

                                                         (DWORD)this);

if(m_hConnect == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetConnect Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        lpMsg = NULL;

        InternetCloseHandle(m_hSession);

        return FALSE;

}

// 發送消息,通知界面開始傳輸了

if(m_hWnd != NULL)

{

        ::PostMessage(       m_hWnd, m_uMsgHandle,

               (WPARAM)ftp_begin, (LPARAM)m_dwTotalFileSize);

}

else if(m_dwThread != 0)

{

        ::PostThreadMessage(m_dwThread, m_uMsgHandle,

               (WPARAM)ftp_begin, (LPARAM)m_dwTotalFileSize);

}

// 建立檔案上傳線程

m_hFtpThread = CreateThread(NULL,

                                                  0,

                                                  FtpClientUploadThread,

                                                  this,

                                                  0,

                                                  &m_dwFtpThread);

if(m_hFtpThread == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("CreateThread Error with %s/n", lpMsg);

        LocalFree(lpMsg);

        InternetCloseHandle(m_hConnect);

        InternetCloseHandle(m_hSession);

        return FALSE;

}

m_bTransfering = TRUE;

return TRUE;

}// End UploadFile

// UploadFile結束

//

//

// 名稱:BeginUpload

// 描述:開始檔案上傳

// 原型:BOOL BeginUpload(HWND hWnd,       // 用于接收消息的視窗句柄

//                                         LPCTSTR lpszRemote,  // 上傳後儲存的檔案名稱

//                                         LPCTSTR lpszLocal,     // 要上傳的檔案

//                                         DWORD dwFileType)   // 檔案傳輸類型

// 參數:

//             [in] hWnd:接收檔案上傳狀态報告的視窗句柄

//             [in] lpszRemote:檔案上傳後在伺服器端儲存的檔案名稱

//             [in] lpszLocal:要上傳的本地檔案路徑

//             [in] dwFileType:檔案上傳的類型

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::BeginUpload(HWND hWnd,

                                                   LPCTSTR lpszRemote,

                                                   LPCTSTR lpszLocal,

                                                   DWORD dwFileType)

{

if(    lpszRemote == NULL ||

        lpszLocal == NULL ||

        (dwFileType != FTP_TRANSFER_TYPE_BINARY &&

        dwFileType != FTP_TRANSFER_TYPE_ASCII &&

        dwFileType != FTP_TRANSFER_TYPE_UNKNOWN) ||

        hWnd == NULL)

        return FALSE;

if(m_bTransfering)

        return FALSE;

m_hWnd = hWnd;

return UploadFile(   lpszRemote,

                                    lpszLocal,

                                    dwFileType);

}// End BeginUpload

// BeginUpload結束

//

//

// 名稱:BeginUpload

// 描述:開始檔案上傳

// 原型:BOOL BeginUpload(DWORD dwThread,      // 用于接收消息的線程句柄

//                                         LPCTSTR lpszRemote,  // 上傳後儲存的檔案名稱

//                                         LPCTSTR lpszLocal,     // 要上傳的檔案

//                                         DWORD dwFileType)   // 檔案傳輸類型

// 參數:

//             [in] dwThread:接收檔案上傳狀态報告的線程句柄

//             [in] lpszRemote:檔案上傳後在伺服器端儲存的檔案名稱

//             [in] lpszLocal:要上傳的本地檔案路徑

//             [in] dwFileType:檔案上傳的類型

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::BeginUpload(DWORD dwThread,

                                                   LPCTSTR lpszRemote,

                                                   LPCTSTR lpszLocal,

                                                   DWORD dwFileType)

{

if(    lpszRemote == NULL ||

        lpszLocal == NULL ||

        (dwFileType != FTP_TRANSFER_TYPE_BINARY &&

        dwFileType != FTP_TRANSFER_TYPE_ASCII &&

        dwFileType != FTP_TRANSFER_TYPE_UNKNOWN) ||

        dwThread == 0)

        return FALSE;

if(m_bTransfering)

        return FALSE;

m_dwThread = dwThread;

return UploadFile(   lpszRemote,

                                    lpszLocal,

                                    dwFileType);

}// End BeginUpload

// BeginUpload結束

//

//

// 名稱:EndFtpFile

// 描述:結束檔案傳輸進行的操作

// 原型:BOOL EndFtpFile()

// 參數:

//    

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::EndFtpFile()

{

if(m_hConnect)

{

        InternetCloseHandle(m_hConnect);

        m_hConnect = NULL;

}

return TRUE;

}// End EndFtpFile

// EndFtpFile結束

//

//

// 名稱:ClearFtpSession

// 描述:清除檔案傳輸會話資源

// 原型:void ClearFtpSession()

// 參數:

//    

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

void CFtpClientCtrl::ClearFtpSession()

{

if(m_hConnect != NULL)

{

        InternetCloseHandle(m_hConnect);

        m_hConnect = NULL;

}

if(m_hSession != NULL)

{

        InternetCloseHandle(m_hSession);

        m_hSession = 0;

}

m_hWnd = NULL;

m_dwThread = 0;

m_bTransfering = FALSE;

}

//

// 名稱:IncreaseFtpSize

// 描述:在檔案傳輸過程中,設定實際已經傳輸的檔案大小

// 原型:DWORD IncreaseFtpSize(DWORD dwStep)       // 本地大小

// 參數:

//             [in] dwStep:本次狀态中傳輸的大小

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

DWORD CFtpClientCtrl::IncreaseFtpSize(DWORD dwStep)

{

if(m_dwCurrentFtpSize < m_dwTotalFileSize)

        m_dwCurrentFtpSize += dwStep;

return m_dwCurrentFtpSize;

}// End IncreaseFtpSize

// IncreaseFtpSize結束

//

//

// 名稱:GetRemoteFileSize

// 描述:擷取遠端檔案的大小

// 原型:DWORD GetRemoteFileSize()

// 參數:

//    

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

DWORD CFtpClientCtrl::GetRemoteFileSize()

{

if(m_szRemote == NULL)

{

        return 0;

}

LPTSTR lpMsg = NULL;

// 開始連接配接網絡

HINTERNET hInternet = InternetOpen(      _T("Ftp_Ctrl"),

                                                                INTERNET_OPEN_TYPE_DIRECT,

                                                                m_szProxyName,

                                                                m_szProxyPwd,

                                                                INTERNET_FLAG_NO_CACHE_WRITE);//INTERNET_FLAG_ASYNC

if(hInternet == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetOpen Error With %d--%s/n", GetLastError(), lpMsg);

        LocalFree(lpMsg);

        return 0;

}

// 連接配接

HINTERNET hConnect = InternetConnect( hInternet,

                                                                       m_szFtpSrvIp,

                                                                       m_wFtpSrvPort,

                                                                       m_szFtpSrvUser,

                                                                       m_szFtpSrvPwd,

                                                                       INTERNET_SERVICE_FTP,

                                                                       INTERNET_FLAG_PASSIVE |

                                                                       INTERNET_FLAG_EXISTING_CONNECT,

                                                                       0);

if(hConnect == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("InternetConnect Error With %d--%s/n", GetLastError(), lpMsg);

        LocalFree(lpMsg);

        InternetCloseHandle(hInternet);

        return 0;

}

// 打開檔案

HINTERNET hFile = FtpOpenFile(       hConnect,

                                                         m_szRemote,

                                                         GENERIC_READ,

                                                         m_dwFileType |

                                                         INTERNET_FLAG_RELOAD |

                                                         INTERNET_FLAG_RESYNCHRONIZE,

                                                         0);

if(hFile == NULL)

{

        FormatFtpError(GetLastError(), &lpMsg);

        TRACE("FtpOpen Error With %d--%s/n", GetLastError(), lpMsg);

        LocalFree(lpMsg);

        InternetCloseHandle(hConnect);

        InternetCloseHandle(hInternet);

        return 0;

}

typedef DWORD (WINAPI *FtpGetFileSize_Proc)(HINTERNET, LPDWORD);

HINSTANCE hInst = LoadLibrary("wininet.dll");

if(hInst == NULL)

{

        TRACE("Load Library failed!/n");

        InternetCloseHandle(hFile);

        InternetCloseHandle(hConnect);

        InternetCloseHandle(hInternet);

        return 0;

}

FtpGetFileSize_Proc pfnFtpGetFileSize =

        (FtpGetFileSize_Proc)GetProcAddress(hInst, "FtpGetFileSize");

if(pfnFtpGetFileSize == NULL)

{

        TRACE("Get Proc FtpGetFileSize Failed!/n");

        InternetCloseHandle(hFile);

        InternetCloseHandle(hConnect);

        InternetCloseHandle(hInternet);

        FreeLibrary(hInst);

        return 0;

}

DWORD dwSize = pfnFtpGetFileSize(hFile, NULL);

FreeLibrary(hInst);

InternetCloseHandle(hFile);

InternetCloseHandle(hConnect);

InternetCloseHandle(hInternet);

return dwSize;

}// End GetRemoteFileSize

// GetRemoteFileSize結束

//

//

// 名稱:GetLocalFileSize

// 描述:擷取本地檔案的大小

// 原型:DWORD GetLocalFileSize()

// 參數:

//    

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

DWORD CFtpClientCtrl::GetLocalFileSize()

{

HANDLE hFile = CreateFile(  m_szLocal,

                                                  0,

                                                  0,

                                                  NULL,

                                                  OPEN_EXISTING,

                                                  FILE_ATTRIBUTE_NORMAL,

                                                  NULL);

if(hFile == INVALID_HANDLE_VALUE)

{

        return -1;

}

DWORD dwSize = GetFileSize(hFile, NULL);

CloseHandle(hFile);

return dwSize;

}// End GetLocalFileSize

// GetLocalFileSize結束

//

//

// 名稱:IsFileAscii

// 描述:判斷檔案的傳輸方式是否為ASCII

// 原型:BOOL IsFileAscii(LPCTSTR lpszFile)   // 檔案名稱

// 參數:

//             [in] lpszFile:要判斷的檔案名稱

// 備注:

//

// 修改記錄

//             日期              版本                            修改人                         修改内容

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

//  2003/09/08      V2.00                 wjr                建立

//________________________________________________________________________

BOOL CFtpClientCtrl::IsFileAscii(LPCTSTR lpszFile)   // 檔案名稱

{

if(lpszFile == NULL)

        return FALSE;

LPCTSTR lpszExt = _tcsrchr(lpszFile, '.');  // 得到檔案字尾

return IsFtpAscii(lpszExt);

}// End IsFileAscii

// IsFileAscii結束

//

使用方法:

// 注冊檔案傳輸控件必要的參數

m_cFtpCtrl.SetServerParam( szNmsIp),             // 網管伺服器位址

                                           szFtpUser,      // ftp伺服器使用者

                                           szFtpPwd);     // ftp伺服器密碼

m_cFtpCtrl.RegisterMsgHandle(WM_ FTP_PROGRESS);

        // 設定檔案傳輸控件的傳輸方向

        m_cFtpCtrl.SetFtpDirect(FALSE);

        if(!m_cFtpCtrl.BeginUpload(  GetSafeHwnd(),

                                                         m_strRemote,

                                                         m_strLocalFile))

        {

               AfxMessageBox(_T("檔案開始上傳失敗!"));

               PostMessage(WM_CLOSE);

               return TRUE;

              }

繼續閱讀