我是靠谱客的博主 清脆金毛,最近开发中收集的这篇文章主要介绍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 %dn", dwInternetStatus);
  // 查询当前文件传输状态
  switch(dwInternetStatus)
  {
  case INTERNET_STATUS_RESOLVING_NAME: // 10
   TRACE("Looking up the IP address for %sn", (LPCTSTR)lpvStatusInformation);
   
  break;
  case INTERNET_STATUS_NAME_RESOLVED: // 11
   TRACE("Name resolved %sn", (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--%sn", (LPCTSTR)lpvStatusInformation);
   
  break;
  case INTERNET_STATUS_SENDING_REQUEST: // 30
   TRACE("Sending requestn");
   
  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,总共数据为:%dn", *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 %dn",
   *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 connectionn");
   
  break;
  case INTERNET_STATUS_CONNECTION_CLOSED: // 51
   TRACE("Connection closedn");
   
  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 proxyn");
   
  break;
  case INTERNET_STATUS_REQUEST_COMPLETE: // 100
   // 一个异步操作已经完成,lpvStatusInformation是INTERNET_ASYNC_RESULT的指针
   {
   LPINTERNET_ASYNC_RESULT ptIAR =
   reinterpret_cast<LPINTERNET_ASYNC_RESULT>(lpvStatusInformation);
   TRACE("一个异步操作完成,错误为:%d,结果为:%dn",
   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 siten");
   {
   LPDWORD pdwRead = (LPDWORD)lpvStatusInformation;
   switch(*pdwRead)
   {
   case INTERNET_STATE_CONNECTED: // 0x00000001
   TRACE("Connected state moved between secure and nonsecure siten");
   
  break;
   case INTERNET_STATE_DISCONNECTED: // 0x00000002
   TRACE("Disconnected from networkn");
   
  break;
   case INTERNET_STATE_DISCONNECTED_BY_USER: // 0x00000010
   TRACE("Disconnected by user requestn");
   
  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 completen");
   
  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--%sn", 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--%sn", 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 %dn", 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 %sn", lpMsg);
   LocalFree(lpMsg);
   lpMsg = NULL;
   return FALSE;
  }
  // 设置状态回调函数
  if(InternetSetStatusCallback(m_hSession, FtpCtrl_CallbackStatus) ==
   INTERNET_INVALID_STATUS_CALLBACK)
  {
   FormatFtpError(GetLastError(), &lpMsg);
   TRACE("InternetSetStatusCallback Error with %sn", 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 %sn", 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 %sn", 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 %dn", 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 %sn", lpMsg);
   LocalFree(lpMsg);
   lpMsg = NULL;
   return FALSE;
  }
  // 设置文件传输状态回调函数
  if(InternetSetStatusCallback(m_hSession, FtpCtrl_CallbackStatus) ==
   INTERNET_INVALID_STATUS_CALLBACK)
  {
   FormatFtpError(GetLastError(), &lpMsg);
   TRACE("InternetSetStatusCallback Error with %sn", 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 %sn", 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 %sn", 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--%sn", 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--%sn", 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--%sn", 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;
   }

最后

以上就是清脆金毛为你收集整理的wininet实现ftp客户端关于传输进度的分析的全部内容,希望文章能够帮你解决wininet实现ftp客户端关于传输进度的分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(30)

评论列表共有 0 条评论

立即
投稿
返回
顶部