#pragma once #include "libEncrypt_MD5.h" typedef DWORD (WINAPI *DOWNANT_STATUS_CALLBACK)(VOID* pOwner, VOID* pDownAnt); #define MANAGER_CMD_CONTINUE (0) //继续下载 #define MANAGER_CMD_FORCEABORT (1) //强制中止 #define MANAGER_CMD_STOPHERE (2) //下载的目前为止 /** 下载器,用于下载一个单独文件 */ class CDownloadAnt { public: //主状态 enum DOWN_STATE_CATEGORY { IDLE, //空闲 BUSY, //忙碌中 FINISH_SUCCESS, //成功下载完毕 FINISH_NOT_SUCCESS, //下载失败 }; enum DOWN_STATE { IDLE_NOTINIT, //空闲 - 尚未初始化 IDLE_INIT_SUCCESS, //空闲 - 初始化成功 IDLE_INIT_FAILED, //空闲 - 初始化失败 BUSY_BEGIN_THREAD, //忙碌中 - 启动下载线程 BUSY_OPEN_REQUEST, //忙碌中 - 发送下载请求 BUSY_RESOLVING_NAME, //忙碌中 - 查找服务器中 BUSY_RESOLVED_NAME, //忙碌中 - 查找完服务器 BUSY_CONNECTING, //忙碌中 - 连接服务器中 BUSY_CONNECTED, //忙碌中 - 连接完服务器 BUSY_REDIRECTING, //忙碌中 - 重新定位中 BUSY_GET_FILE_INFORMATION, //忙碌中 - 取得文件信息 BUSY_BEGIN_DOWNFILE, //忙碌中 - 开始下载文件中 FINISH_SUCCESS_OVER, //成功下载完毕 FINISH_SUCCESS_STOPHERE, //用户定义下载完毕 FINISH_FORCEABORT, //下载失败 - 用于取消 FINISH_ERROR_UNSUPPORTED_SCHEME, //下载失败 - 不支持的协议 FINISH_ERROR_TIMEOUT, //下载失败 - 超时 FINISH_ERROR_TRY_OPEN_LOCALFILE, //下载失败 - 生成本地文件失败 FINISH_ERROR_INTERNET_OPEN, //下载失败 - 打开Internet句柄失败 FINISH_ERROR_SETSTATUSCALLBACK, //下载失败 - 设置状态回调函数失败 FINISH_ERROR_INTERNETCONNECT, //下载失败 - 连接Internet失败 FINISH_ERROR_OPENREQUEST, //下载失败 - 生成Request失败 FINISH_ERROR_SENDREQUEST, //下载失败 - 发送Request失败 FINISH_ERROR_QUERYINFO, //下载失败 - 查询信息 FINISH_ERROR_NEED_PROXY_AUTH_REQ, //下载失败 - 需要代理服务器登录 FINISH_ERROR_DENIED, //下载失败 - 被服务器拒绝 FINISH_ERROR_INVALID_HTTP_RESPONSE, //下载失败 - 非法的HTTP请求 FINISH_ERROR_READFILE, //下载失败 - 读取Internet文件失败 FINISH_ERROR_EXCEPTION, //下载失败 - 有异常抛出 }; public: /** 初始化下载器 @param wszURLToDownload - 网络文件地址 @param wszFileToDownloadInto - 本地文件地址 @param pOwner - 参数,会被传入回调函数 @param funcUserCallBack - 回调函数 @param nOverTime - 超时时间 */ bool init(const wchar_t* wszURLToDownload, const wchar_t* wszFileToDownloadInto, DOWNANT_STATUS_CALLBACK funcUserCallBack = NULL, void* pOwner = NULL, unsigned int nOverTime = INFINITE); /** 启动下载 @param block - 是否等待下载结束后再退出 */ void begin(bool block); const wchar_t* getDownUrl(void) const { return m_wszURLToDownload; } const wchar_t* getLocalFile(void) const { return m_wszFileToDownloadInto; } const wchar_t* getServer(void) const { return m_wszServer; } bool checkMD5(const char* md5_string) const; DOWN_STATE getState(void) const { return m_theState; } DOWN_STATE_CATEGORY getStateCategory(void) const { return m_theStateCategory; } protected: //下载单位4K enum { DOWNANT_MINSIZE = 1024*4 }; HANDLE m_hThread; //!< 下载线程句柄 DOWN_STATE_CATEGORY m_theStateCategory; //!< 主状态 DOWN_STATE m_theState; //!< 详细状态 void* m_pOwner; //!< 附加属性,这个值会传给回调函数 /** 下载文件的地址 */ wchar_t m_wszURLToDownload[INTERNET_MAX_URL_LENGTH]; /** 本地存贮地址 */ wchar_t m_wszFileToDownloadInto[MAX_PATH]; MD5Digest m_fileMD5; //!< 所下载文件的文件MD5码 INTERNET_SCHEME m_schemeType; //!< 服务段类型http,ftp wchar_t m_wszServer[MAX_PATH]; //!< 服务器地址 wchar_t m_wszObject[INTERNET_MAX_URL_LENGTH]; //!< 文件在服务器上的位置 WORD m_nPort; //!< 服务器端口 /// WinInet所用的句柄 HINTERNET m_hInternetSession; HINTERNET m_hHttpConnection; HINTERNET m_hHttpFile; //用户命令 DWORD m_dwUserCmd; //超时时限(秒) DWORD m_nOverTime; //开始时间 ULONGLONG m_beginTime; //是否得到了文件大小 BOOL m_bGotFileSize; //文件总大小 int64_t m_dwFileSizeTotal; //已经下载的文件大小 int64_t m_dwFileSizeRead; //文件存储句柄 FILE* m_fpFileToWrite; //回调函数 DOWNANT_STATUS_CALLBACK UserCallBack; //状态描述 wchar_t m_wszStatusInfor[MAX_PATH]; public: CDownloadAnt(); ~CDownloadAnt(); private: /** wininet 回调函数 */ static void CALLBACK _onWininetStatusCallBack(HINTERNET hInternet, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength); void onWininetStatusCallBack(HINTERNET hInternet, DWORD dwInternetStatus, LPVOID lpvStatusInformation, DWORD dwStatusInformationLength); /** 线程入口函数 */ static UINT CALLBACK _downloadThread(void* pParam); void downloadThread(void); /** 改变状态 */ void setStatus(DOWN_STATE newState); /** 状态改变回调函数 */ void onStatusCallback(void); /** 检查是否需要强制退出(超时或者用户强制终止) */ BOOL _checkAbort(void); };