1、第一次感觉MS也有这么难用的MFC类;
2、CFtpFileFind类只能实例化一个,多个实例同时查找会出错(因此下载时不能递归),采用队列存储目录再依次下载;
3、本程序支持文件夹嵌套上传下载;
4、boost::filesystem::create_directory不能递归创建文件夹,需手动实现
5、同时支持文件夹先打包压缩再上传功能(m_bZibFlag控制是否压缩)
代码如下:
CFtpClient.h
1 #ifndef __ftp_client_h__ 2 #define __ftp_client_h__ 3 4 #include <afxinet.h> 5 #include <iostream> 6 #include <sstream> 7 #include <queue> 8 #include <boost/filesystem/operations.hpp> 9 #include <boost/filesystem/path.hpp> 10 #include "zip.h" 11 12 class CFtpClient 13 { 14 public: 15 CFtpClient(); 16 ~CFtpClient(); 17 18 bool Connect(); 19 bool Close(); 20 int Download(std::string strServerDir = "\\", std::string strFilename = "*"); 21 int Upload(const std::string strLocalPath); 22 private: 23 //下载文件夹 24 int DownloadFolder(); 25 //下载文件 26 int DownloadFile(std::string strServerDir, std::string strFilename); 27 //创建多级目录 28 void CreateDirectory(boost::filesystem::path path); 29 //获取打包压缩文件名称 30 std::string GetZipFolder(const std::string strFolderPath); 31 //压缩文件夹打包 32 void MakeZipFolder(HZIP hz, const std::string strRoot, const std::string strFolderPath); 33 private: 34 CInternetSession* m_pInternetSession; 35 CFtpConnection* m_pFtpConnection; 36 37 //参数配置 38 std::string m_strServerAddress; //FTP:服务器地址 39 int m_nServerPort; //FTP:服务器端口号 40 std::string m_strUsername; //FTP:登录用户名 41 std::string m_strPassword; //FTP:登录密码 42 bool m_bZibFlag; //文件夹打包上传标志[true:先压缩文件夹打包再上传,false:直接上传文件夹] 43 44 std::string m_strUploadServerDir; //上传服务器存储目录 45 std::string m_strDownloadLocalDir; //下载本地存储目录 46 std::queue<std::string> queServerDir; //等待下载目录队列 47 }; 48 49 50 #endif
CFtpClient.cpp
1 //------------------------------------------------------------------------------ 2 // 版权声明:转载请注明出处 5 // 模块名称: 6 // 模块描述:FTP上传下载类 7 // 开发作者:可笑痴狂 http://www.cnblogs.com/dongsheng/ 8 // 创建日期:2015-12-10 9 // 模块版本:1.0.0.0 10 // 备注:压缩算法引入zip.h和zip.cpp文件,无需lib或dll, 11 // 详情参考:http://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win 12 //------------------------------------------------------------------------------ 13 14 #include <string> 15 #include <iostream> 16 #include <sstream> 17 #include "CFtpClient.h" 18 #include <boost/assert.hpp> 19 #include <boost/lexical_cast.hpp> 20 #include <boost/foreach.hpp> 21 22 23 CFtpClient::CFtpClient() 24 { 25 m_pInternetSession = NULL; 26 m_pFtpConnection = NULL; 27 m_strServerAddress = "127.0.0.1"; 28 m_strUsername = "123"; 29 m_strPassword = "123"; 30 m_nServerPort = 21; 31 m_strDownloadLocalDir = "D:\\DownloadLocal"; 32 m_strUploadServerDir = "\\"; 33 m_bZibFlag = true; 34 } 35 36 CFtpClient::~CFtpClient() 37 { 38 this->Close(); 39 } 40 41 bool CFtpClient::Connect() 42 { 43 if (m_pInternetSession != NULL) 44 { 45 return true; 46 } 47 48 m_pInternetSession = new CInternetSession("OTC_FTP_Client"); 49 int nCnt = 1; 50 while(nCnt++) 51 { 52 try 53 { 54 m_pFtpConnection = m_pInternetSession->GetFtpConnection(m_strServerAddress.c_str(), m_strUsername.c_str(), m_strPassword.c_str(),
m_nServerPort); 55 } 56 catch(CInternetException *pEx) 57 { 58 char szErrMsg[1024+1] = {0}; 59 if (pEx->GetErrorMessage(szErrMsg, 1024)) 60 { 61 std::cout << "连接FTP服务器失败, ErrMsg:" << szErrMsg << std::endl; 62 if (nCnt > 5) 63 { 64 return false; 65 } 66 std::cout << "正在尝试重新连接[" << nCnt-1 << "]......" << std::endl; 67 } 68 continue; 69 } 70 return true; 71 } 72 73 return true; 74 } 75 76 bool CFtpClient::Close() 77 { 78 if (NULL != m_pInternetSession) 79 { 80 m_pInternetSession->Close(); 81 delete m_pInternetSession; 82 m_pInternetSession = NULL; 83 } 84 if (NULL != m_pFtpConnection) 85 { 86 m_pFtpConnection->Close(); 87 delete m_pFtpConnection; 88 m_pFtpConnection = NULL; 89 } 90 91 return true; 92 } 93 int CFtpClient::Download(std::string strServerDir /*="\\"*/, std::string strFilename /*= "*"*/) 94 { 95 if ("*" == strFilename) 96 { 97 queServerDir.push(strServerDir); 98 return this->DownloadFolder(); 99 } 100 else 101 { 102 return this->DownloadFile(strServerDir, strFilename); 103 } 104 105 } 106 int CFtpClient::DownloadFile(std::string strServerDir, std::string strFilename) 107 { 108 int nRet = 0; 109 CFtpFileFind* pFtpFileFind = NULL; 110 if(!this->Connect()) 111 { 112 nRet = -1; 113 goto __end; 114 } 115 else 116 { 117 boost::filesystem::path LocalPath(m_strDownloadLocalDir); 118 if (!boost::filesystem::exists(LocalPath)) 119 { 120 this->CreateDirectory(LocalPath); 121 } 122 if (0 == m_pFtpConnection->SetCurrentDirectory(strServerDir.c_str())) 123 { 124 nRet = -1; 125 std::cout << "设置服务器下载目录[" << strServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 126 DWORD dw = 0; 127 char szBuf[512]={0}; 128 DWORD dwLen = sizeof(szBuf)-1; 129 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 130 std::cout << "错误信息:" << szBuf << std::endl; 131 goto __end; 132 } 133 if (pFtpFileFind == NULL) 134 { 135 pFtpFileFind = new CFtpFileFind(m_pFtpConnection); 136 } 137 int nRet = pFtpFileFind->FindFile(strFilename.c_str()); 138 if(nRet) 139 { 140 nRet = pFtpFileFind->FindNextFile(); 141 142 std::string strLocalFilename = m_strDownloadLocalDir + "\\" + strFilename; 143 std::string strServerFilename = strFilename; 144 if(m_pFtpConnection->GetFile(strServerFilename.c_str(), strLocalFilename.c_str(), FALSE)) 145 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]成功!" << std::endl; 146 else 147 { 148 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]失败!" << std::endl; 149 char szBuf[512]={0}; 150 DWORD dw = 0; 151 DWORD dwLen = sizeof(szBuf)-1; 152 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 153 dw = GetLastError(); 154 std::cout << "错误信息:" << szBuf << std::endl; 155 nRet = -1; 156 } 157 } 158 } 159 __end: 160 this->Close(); 161 if (pFtpFileFind) 162 { 163 pFtpFileFind->Close(); 164 delete pFtpFileFind; 165 } 166 167 return nRet; 168 } 169 int CFtpClient::DownloadFolder() 170 { 171 std::string strServerDir; 172 std::string strFilename; 173 CFtpFileFind* pFtpFileFind = NULL; 174 int nRet = 0; 175 176 if(!this->Connect()) 177 { 178 nRet = -1; 179 goto __end; 180 } 181 else 182 { 183 while(!queServerDir.empty()) 184 { 185 strServerDir = queServerDir.front(); 186 queServerDir.pop(); 187 188 boost::filesystem::path LocalPath(m_strDownloadLocalDir); 189 if (!boost::filesystem::exists(LocalPath / strServerDir)) 190 { 191 this->CreateDirectory(LocalPath / strServerDir); 192 } 193 194 if (0 == m_pFtpConnection->SetCurrentDirectory(strServerDir.c_str())) 195 { 196 nRet = -1; 197 std::cout << "设置服务器下载目录[" << strServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 198 DWORD dw = 0; 199 char szBuf[512]={0}; 200 DWORD dwLen = sizeof(szBuf)-1; 201 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 202 std::cout << "错误信息:" << szBuf << std::endl; 203 goto __end; 204 } 205 if (pFtpFileFind == NULL) 206 { 207 pFtpFileFind = new CFtpFileFind(m_pFtpConnection); 208 } 209 210 int nRet = pFtpFileFind->FindFile(); 211 while(nRet) 212 { 213 nRet = pFtpFileFind->FindNextFile(); 214 strFilename = pFtpFileFind->GetFilePath(); 215 if (pFtpFileFind->IsDirectory()) 216 { 217 queServerDir.push(std::string(pFtpFileFind->GetFilePath())); 218 continue; 219 } 220 221 std::string strLocalFilename = m_strDownloadLocalDir + strFilename; 222 std::string strServerFilename = strFilename; 223 224 if(m_pFtpConnection->GetFile(strServerFilename.c_str(), strLocalFilename.c_str(), FALSE)) 225 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]成功!" << std::endl; 226 else 227 { 228 std::cout << "下载文件[" << strServerFilename << "]到[" << strLocalFilename << "]失败!" << std::endl; 229 char szBuf[512]={0}; 230 DWORD dw = 0; 231 DWORD dwLen = sizeof(szBuf)-1; 232 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 233 dw = GetLastError(); 234 std::cout << "错误信息:" << szBuf << std::endl; 235 nRet = -1; 236 } 237 } 238 } 239 } 240 __end: 241 this->Close(); 242 if (pFtpFileFind != NULL) 243 { 244 pFtpFileFind->Close(); 245 delete pFtpFileFind; 246 } 247 return nRet; 248 } 249 250 int CFtpClient::Upload(const std::string strLocalPath) 251 { 252 int nRet = 0; 253 CFtpFileFind* pFtpFileFind = NULL; 254 boost::filesystem::path localPath(strLocalPath); 255 256 if (m_bZibFlag) 257 {//文件夹先压缩再上传 258 if (boost::filesystem::exists(localPath)) 259 { 260 if (boost::filesystem::is_directory(localPath)) 261 { 262 std::string strUploadName = this->GetZipFolder(localPath.string()); 263 localPath = strUploadName;//改为上传压缩文件 264 } 265 } 266 else 267 { 268 std::cout << "指定上传文件不存在!" << std::endl; 269 nRet = -1; 270 goto __end; 271 } 272 } 273 274 275 //由于压缩大文件很耗时,为防止长时间占用FTP连接产生的异常,因此先压缩文件后连接上传。 276 if(!this->Connect()) 277 { 278 nRet = -1; 279 goto __end; 280 } 281 else 282 { 283 if (0 == m_pFtpConnection->SetCurrentDirectory(m_strUploadServerDir.c_str())) 284 { 285 nRet = -1; 286 std::cout << "设置服务器上传目录[" << m_strUploadServerDir << "]失败!ErrCode=" << GetLastError() << std::endl; 287 DWORD dw = 0; 288 char szBuf[512]={0}; 289 DWORD dwLen = sizeof(szBuf)-1; 290 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 291 std::cout << "错误信息:" << szBuf << std::endl; 292 goto __end; 293 } 294 295 if (boost::filesystem::exists(localPath)) 296 { 297 if (boost::filesystem::is_directory(localPath)) 298 { 299 m_pFtpConnection->CreateDirectory(localPath.leaf().string().c_str()); 300 301 //directory_iterator:只支持本层目录遍历 302 boost::filesystem::directory_iterator itor_begin(localPath); 303 boost::filesystem::directory_iterator itor_end; 304 305 std::string strServerDir = m_strUploadServerDir; 306 for (; itor_begin != itor_end; itor_begin++) 307 {//回溯算法 308 m_strUploadServerDir += std::string("\\") + localPath.leaf().string(); 309 this->Upload(itor_begin->path().string()); 310 m_strUploadServerDir = strServerDir; 311 } 312 313 } 314 else 315 { 316 if(m_pFtpConnection->PutFile(localPath.string().c_str(), localPath.leaf().string().c_str(), 317 FTP_TRANSFER_TYPE_BINARY,0)) 318 std::cout << "上传文件[" << localPath.leaf().string() << "]成功!" << std::endl; 319 else 320 { 321 DWORD dw0 = GetLastError(); 322 if (dw0) 323 { 324 char szBuf[512]={0}; 325 DWORD dw = 0; 326 DWORD dwLen = sizeof(szBuf)-1; 327 InternetGetLastResponseInfo(&dw, szBuf, &dwLen); 328 std::cout << "上传文件[" << localPath.leaf().string() << "]失败!ErrCode:" << dw0 << "ErrMsg:" << szBuf << std::endl; 329 goto __end; 330 } 331 } 332 } 333 } 334 else 335 { 336 std::cout << "指定上传文件不存在!" << std::endl; 337 nRet = -1; 338 goto __end; 339 } 340 } 341 342 __end: 343 if (pFtpFileFind != NULL) 344 { 345 pFtpFileFind->Close(); 346 delete pFtpFileFind; 347 } 348 this->Close(); 349 return nRet; 350 } 351 352 void CFtpClient::CreateDirectory(boost::filesystem::path path) 353 { 354 boost::filesystem::path::iterator itor = path.begin(); 355 boost::filesystem::path pathTmp; 356 while(itor != path.end()) 357 { 358 pathTmp /= (*itor).string(); 359 if (!pathTmp.empty() && !boost::filesystem::exists(pathTmp)) 360 { 361 boost::filesystem::create_directory(pathTmp); 362 } 363 ++itor; 364 } 365 } 366 367 std::string CFtpClient::GetZipFolder(const std::string strFolderPath) 368 { 369 boost::filesystem::path pathFolder(strFolderPath); 370 std::string strZipName = strFolderPath + ".zip"; 371 std::string strRootPath = pathFolder.branch_path().string(); 372 373 HZIP hz = CreateZip(strZipName.c_str(), 0); 374 this->MakeZipFolder(hz, strRootPath, strFolderPath); 375 CloseZip(hz); 376 377 return strZipName; 378 } 379 380 void CFtpClient::MakeZipFolder(HZIP hz, const std::string strRoot, const std::string strFolderPath) 381 { 382 boost::filesystem::path FolderPath(strFolderPath); 383 ZipAddFolder(hz, FolderPath.leaf().string().c_str()); 384 385 //recursive_directory_iterator:支持深层目录遍历 386 boost::filesystem::recursive_directory_iterator itor_begin(FolderPath); 387 boost::filesystem::recursive_directory_iterator itor_end; 388 389 for (; itor_begin != itor_end; itor_begin++) 390 { 391 std::cout << "正在压缩文件:" << itor_begin->path().string() << "......" << std::endl; 392 std::string strFilePath = itor_begin->path().string(); 393 int nPos = strFilePath.find(strRoot); 394 if (nPos != std::string::npos) 395 {//取得相对于压缩文件本身的路径 396 strFilePath = strFilePath.substr(nPos+strRoot.length()); 397 } 398 399 if (boost::filesystem::is_directory(*itor_begin)) 400 { 401 ZipAddFolder(hz, strFilePath.c_str()); 402 } 403 else 404 { 405 ZipAdd(hz, strFilePath.c_str(), itor_begin->path().string().c_str()); 406 } 407 } 408 }
zip.h
1 #ifndef _zip_H 2 #define _zip_H 3 // 4 #ifdef ZIP_STD 5 #include <time.h> 6 #define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name 7 #ifndef MAX_PATH 8 #define MAX_PATH 1024 9 #endif 10 typedef unsigned long DWORD; 11 typedef char TCHAR; 12 typedef FILE* HANDLE; 13 typedef time_t FILETIME; 14 #endif 15 16 // ZIP functions -- for creating zip files 17 // This file is a repackaged form of the Info-Zip source code available 18 // at www.info-zip.org. The original copyright notice may be found in 19 // zip.cpp. The repackaging was done by Lucian Wischik to simplify and 20 // extend its use in Windows/C++. Also to add encryption and unicode. 21 22 23 #ifndef _unzip_H 24 DECLARE_HANDLE(HZIP); 25 #endif 26 // An HZIP identifies a zip file that is being created 27 28 typedef DWORD ZRESULT; 29 // return codes from any of the zip functions. Listed later. 30 31 32 33 HZIP CreateZip(const TCHAR *fn, const char *password); 34 HZIP CreateZip(void *buf,unsigned int len, const char *password); 35 HZIP CreateZipHandle(HANDLE h, const char *password); 36 // CreateZip - call this to start the creation of a zip file. 37 // As the zip is being created, it will be stored somewhere: 38 // to a pipe: CreateZipHandle(hpipe_write); 39 // in a file (by handle): CreateZipHandle(hfile); 40 // in a file (by name): CreateZip("c:\\test.zip"); 41 // in memory: CreateZip(buf, len); 42 // or in pagefile memory: CreateZip(0, len); 43 // The final case stores it in memory backed by the system paging file, 44 // where the zip may not exceed len bytes. This is a bit friendlier than 45 // allocating memory with new[]: it won't lead to fragmentation, and the 46 // memory won't be touched unless needed. That means you can give very 47 // large estimates of the maximum-size without too much worry. 48 // As for the password, it lets you encrypt every file in the archive. 49 // (This api doesn't support per-file encryption.) 50 // Note: because pipes don't allow random access, the structure of a zipfile 51 // created into a pipe is slightly different from that created into a file 52 // or memory. In particular, the compressed-size of the item cannot be 53 // stored in the zipfile until after the item itself. (Also, for an item added 54 // itself via a pipe, the uncompressed-size might not either be known until 55 // after.) This is not normally a problem. But if you try to unzip via a pipe 56 // as well, then the unzipper will not know these things about the item until 57 // after it has been unzipped. Therefore: for unzippers which don't just write 58 // each item to disk or to a pipe, but instead pre-allocate memory space into 59 // which to unzip them, then either you have to create the zip not to a pipe, 60 // or you have to add items not from a pipe, or at least when adding items 61 // from a pipe you have to specify the length. 62 // Note: for windows-ce, you cannot close the handle until after CloseZip. 63 // but for real windows, the zip makes its own copy of your handle, so you 64 // can close yours anytime. 65 66 67 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, const TCHAR *fn); 68 ZRESULT ZipAdd(HZIP hz,const TCHAR *dstzn, void *src,unsigned int len); 69 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h); 70 ZRESULT ZipAddHandle(HZIP hz,const TCHAR *dstzn, HANDLE h, unsigned int len); 71 ZRESULT ZipAddFolder(HZIP hz,const TCHAR *dstzn); 72 // ZipAdd - call this for each file to be added to the zip. 73 // dstzn is the name that the file will be stored as in the zip file. 74 // The file to be added to the zip can come 75 // from a pipe: ZipAddHandle(hz,"file.dat", hpipe_read); 76 // from a file: ZipAddHandle(hz,"file.dat", hfile); 77 // from a filen: ZipAdd(hz,"file.dat", "c:\\docs\\origfile.dat"); 78 // from memory: ZipAdd(hz,"subdir\\file.dat", buf,len); 79 // (folder): ZipAddFolder(hz,"subdir"); 80 // Note: if adding an item from a pipe, and if also creating the zip file itself 81 // to a pipe, then you might wish to pass a non-zero length to the ZipAddHandle 82 // function. This will let the zipfile store the item's size ahead of the 83 // compressed item itself, which in turn makes it easier when unzipping the 84 // zipfile from a pipe. 85 86 ZRESULT ZipGetMemory(HZIP hz, void **buf, unsigned long *len); 87 // ZipGetMemory - If the zip was created in memory, via ZipCreate(0,len), 88 // then this function will return information about that memory block. 89 // buf will receive a pointer to its start, and len its length. 90 // Note: you can't add any more after calling this. 91 92 ZRESULT CloseZip(HZIP hz); 93 // CloseZip - the zip handle must be closed with this function. 94 95 unsigned int FormatZipMessage(ZRESULT code, TCHAR *buf,unsigned int len); 96 // FormatZipMessage - given an error code, formats it as a string. 97 // It returns the length of the error message. If buf/len points 98 // to a real buffer, then it also writes as much as possible into there. 99 100 101 102 // These are the result codes: 103 #define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, 104 #define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. 105 // The following come from general system stuff (e.g. files not openable) 106 #define ZR_GENMASK 0x0000FF00 107 #define ZR_NODUPH 0x00000100 // couldn't duplicate the handle 108 #define ZR_NOFILE 0x00000200 // couldn't create/open the file 109 #define ZR_NOALLOC 0x00000300 // failed to allocate some resource 110 #define ZR_WRITE 0x00000400 // a general error writing to the file 111 #define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip 112 #define ZR_MORE 0x00000600 // there's still more data to be unzipped 113 #define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile 114 #define ZR_READ 0x00000800 // a general error reading the file 115 // The following come from mistakes on the part of the caller 116 #define ZR_CALLERMASK 0x00FF0000 117 #define ZR_ARGS 0x00010000 // general mistake with the arguments 118 #define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't 119 #define ZR_MEMSIZE 0x00030000 // the memory size is too small 120 #define ZR_FAILED 0x00040000 // the thing was already failed when you called this function 121 #define ZR_ENDED 0x00050000 // the zip creation has already been closed 122 #define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken 123 #define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped 124 #define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip 125 // The following come from bugs within the zip library itself 126 #define ZR_BUGMASK 0xFF000000 127 #define ZR_NOTINITED 0x01000000 // initialisation didn't work 128 #define ZR_SEEK 0x02000000 // trying to seek in an unseekable file 129 #define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed 130 #define ZR_FLATE 0x05000000 // an internal error in the de/inflation code 131 132 133 134 135 136 137 // e.g. 138 // 139 // (1) Traditional use, creating a zipfile from existing files 140 // HZIP hz = CreateZip("c:\\simple1.zip",0); 141 // ZipAdd(hz,"znsimple.bmp", "c:\\simple.bmp"); 142 // ZipAdd(hz,"znsimple.txt", "c:\\simple.txt"); 143 // CloseZip(hz); 144 // 145 // (2) Memory use, creating an auto-allocated mem-based zip file from various sources 146 // HZIP hz = CreateZip(0,100000, 0); 147 // // adding a conventional file... 148 // ZipAdd(hz,"src1.txt", "c:\\src1.txt"); 149 // // adding something from memory... 150 // char buf[1000]; for (int i=0; i<1000; i++) buf[i]=(char)(i&0x7F); 151 // ZipAdd(hz,"file.dat", buf,1000); 152 // // adding something from a pipe... 153 // HANDLE hread,hwrite; CreatePipe(&hread,&hwrite,NULL,0); 154 // HANDLE hthread = CreateThread(0,0,ThreadFunc,(void*)hwrite,0,0); 155 // ZipAdd(hz,"unz3.dat", hread,1000); // the '1000' is optional. 156 // WaitForSingleObject(hthread,INFINITE); 157 // CloseHandle(hthread); CloseHandle(hread); 158 // ... meanwhile DWORD WINAPI ThreadFunc(void *dat) 159 // { HANDLE hwrite = (HANDLE)dat; 160 // char buf[1000]={17}; 161 // DWORD writ; WriteFile(hwrite,buf,1000,&writ,NULL); 162 // CloseHandle(hwrite); 163 // return 0; 164 // } 165 // // and now that the zip is created, let's do something with it: 166 // void *zbuf; unsigned long zlen; ZipGetMemory(hz,&zbuf,&zlen); 167 // HANDLE hfz = CreateFile("test2.zip",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); 168 // DWORD writ; WriteFile(hfz,zbuf,zlen,&writ,NULL); 169 // CloseHandle(hfz); 170 // CloseZip(hz); 171 // 172 // (3) Handle use, for file handles and pipes 173 // HANDLE hzread,hzwrite; CreatePipe(&hzread,&hzwrite,0,0); 174 // HANDLE hthread = CreateThread(0,0,ZipReceiverThread,(void*)hzread,0,0); 175 // HZIP hz = CreateZipHandle(hzwrite,0); 176 // // ... add to it 177 // CloseZip(hz); 178 // CloseHandle(hzwrite); 179 // WaitForSingleObject(hthread,INFINITE); 180 // CloseHandle(hthread); 181 // ... meanwhile DWORD WINAPI ZipReceiverThread(void *dat) 182 // { HANDLE hread = (HANDLE)dat; 183 // char buf[1000]; 184 // while (true) 185 // { DWORD red; ReadFile(hread,buf,1000,&red,NULL); 186 // // ... and do something with this zip data we're receiving 187 // if (red==0) break; 188 // } 189 // CloseHandle(hread); 190 // return 0; 191 // } 192 193 194 195 // Now we indulge in a little skullduggery so that the code works whether 196 // the user has included just zip or both zip and unzip. 197 // Idea: if header files for both zip and unzip are present, then presumably 198 // the cpp files for zip and unzip are both present, so we will call 199 // one or the other of them based on a dynamic choice. If the header file 200 // for only one is present, then we will bind to that particular one. 201 ZRESULT CloseZipZ(HZIP hz); 202 unsigned int FormatZipMessageZ(ZRESULT code, char *buf,unsigned int len); 203 bool IsZipHandleZ(HZIP hz); 204 #ifdef _unzip_H 205 #undef CloseZip 206 #define CloseZip(hz) (IsZipHandleZ(hz)?CloseZipZ(hz):CloseZipU(hz)) 207 #else 208 #define CloseZip CloseZipZ 209 #define FormatZipMessage FormatZipMessageZ 210 #endif 211 212 213 214 #endif