wininet实现ftp客户端关于传输进度的分析

本文介绍如何使用WinInet API实现FTP文件传输过程中的进度监控,包括下载和上传操作。通过设置状态回调函数,可以实时报告传输进度并计算传输速率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


作者:   来源:csdn    更新日期:2002-08-06   
 

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_beginlparam表示要传输的文件大小

        ftp_transfer,    // 对于该事件,wparam = ftp_transferlParam表示已经传输的大小

        ftp_end                 // 对于该事件,wparam = ftp_endlparam表示结果,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;

}

 

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值