|
使用示例代码片段
void CtestFTPDlg::startUpload(){CString usrpwd(L"lijun:123456");m_ftp.setServeAddr(url.GetBuffer(MAX_PATH),usrpwd.GetBuffer(MAX_PATH) );m_ftp.setCaller(this);SetTimer(0xf01,500,NULL);m_ftp.uploadFile(fn.GetBuffer(MAX_PATH));KillTimer(0xf01);if (m_bSuccess){m_ctlProgress.SetPos(100);AfxMessageBox(L"上传文件成功!");}else{AfxMessageBox(L"上传文件失败!");m_ctlProgress.SetPos(0);}}void CtestFTPDlg::OnBnClickedDeletefile(){// TODO: Add your control notification handler code herem_ftp.abort();CString usrpwd(L"lijun:123456");m_ctlAddr.GetWindowText(url);m_ftp.setServeAddr(url.GetBuffer(MAX_PATH),usrpwd.GetBuffer(MAX_PATH) );m_ftp.deleteFile(std::wstring(L"a.txt"));}
CurlFTP.h源文件清单
#pragma once#include <curl/curl.h>#include <string>/*功能:上传文件到FTP服务器,支持进度条,支持上传操作完成后通知调用者线程。限制:[1]当前进程只能有一个CCurlFTP实例[2]当前进程只能一个个文件上传作者:kagula时间:2010-08-19环境:VS2008SP1 + libcurl 7.21.1 + boost 1.43备注:可以从下面的URL下载libcurl,并编译成DLL(Release)形式!http://curl.haxx.se/libcurl/《libcurl教程》http://blog.csdn.net/JGood/archive/2009/11/08/4787670.aspx索引关键词:VC实现上传文件到Windows FTP服务器*/#define _CF_BUF_SIZE_ 256//下面是回调Classclass IUploadEvent{public://回调函数只是完成变量之间赋值,必须马上返回控制权给CCurlFTP实例所在的线程//通知当前进度,取值范围0~1virtual void setProgress(float fV)=0;//通知上传操作完成,true成功,false失败!virtual void done(bool bSuccess)=0;};//下面是实现上传功能的Classclass CCurlFTP{public:CCurlFTP(void);~CCurlFTP(void);/********************************以下为外部接口*************************************///设置FTP服务器地址//入口参数:ip: URL地址// usrpwd:用户名:密码 注意:中间用“:”符号分隔//接口使用示例:ip=L"ftp://192.168.0.211"; usrpwd=L"lijun:123456";void setServeAddr(const wchar_t *ip,const wchar_t *usrpwd){w2c(ip,m_ip,wcslen(ip)*2+1);w2c(usrpwd,m_usrpwd,wcslen(usrpwd)*2+1);}//上传文件名为filename的文件到FTP服务器。注意,这是个同步函数!//参数说明:源文件名(可以是绝对路径),上传后文件名//接口使用示例:filename=L"待上传测试文件.rar";uploadFilename=NULL;不更改文件名bool uploadFile(wchar_t *filename,wchar_t *uploadFilename=NULL);//设置回调实例void setCaller(IUploadEvent *call){m_call = call;}//取消当前上传任务void abort();//当前上传任务是否在运行bool isRun(){return m_bRun;}//删除指定的文件,删除成功返回truebool deleteFile(std::wstring filename);/********************************以下为内部接口*************************************///读取文件中的数据。回调函数static size_t readFromDisk(char *bufptr, size_t size, size_t nitems, void *userp);char * w2c(const wchar_t *pwstr,char *pcstr, size_t len);private:staticcurl_off_t m_filesize;static bool m_bAbort;//当前是否在执行上传操作,若是m_bRun=true,elsewise the variable m_bRun is false!staticbool m_bRun;CURL * m_easyhandle;char m_ip[_CF_BUF_SIZE_];char m_usrpwd[_CF_BUF_SIZE_];char m_errbuf[_CF_BUF_SIZE_];wchar_t m_filename[_CF_BUF_SIZE_];static IUploadEvent *m_call;bool isFileExist(wchar_t * filename);bool isFileRead(wchar_t * filename);char * makeFullName(char *ip,wchar_t * filename,wchar_t * uploadfilename);};
CurlFTP.cpp源文件清单
//#include "StdAfx.h"#include "CurlFTP.h"#include <io.h>#include <stdlib.h>#include <boost/thread/mutex.hpp>#include <boost/thread/locks.hpp>boost::mutex g_ftp;IUploadEvent *CCurlFTP::m_call = NULL;curl_off_t CCurlFTP::m_filesize = 0;bool CCurlFTP::m_bRun = false;bool CCurlFTP::m_bAbort = false;CCurlFTP::CCurlFTP(void){memset(m_ip,0,sizeof(m_ip));memset(m_usrpwd,0,sizeof(m_usrpwd));m_bRun = false;}CCurlFTP::~CCurlFTP(void){}//return the number of bytes it wrote in the buffer. Returning 0 will signal the end of the uploadsize_t CCurlFTP::readFromDisk(char *bufptr, size_t size, size_t nitems, void *userp){boost::lock_guard<boost::mutex> l(g_ftp);#define fp ((FILE*)userp)static int nRead;if (fp==NULL||CCurlFTP::m_bRun==false||feof(fp)||CCurlFTP::m_bAbort)return 0;//显示当前文件位置if (CCurlFTP::m_call){int nPos;nPos = ftell(fp);m_call->setProgress( nPos/( (float)CCurlFTP::m_filesize ) );}//从磁盘中读数据,通常size=1,nitems=16*1024nRead = fread(bufptr,size,nitems,fp);if (nRead >0)return nRead;return 0;}bool CCurlFTP::uploadFile(wchar_t *bufFileName,wchar_t *uploadFilename){//待上传文件是否存在if (!isFileExist(bufFileName)){OutputDebugString(L"[CCurlFTP::uploadFile]文件不存在/n");return false;}//待上传文件是否可读if (!isFileRead(bufFileName)){OutputDebugString(L"[CCurlFTP::uploadFile]文件无法读取/n");return false;}if (m_bRun){OutputDebugString(L"[CCurlFTP::uploadFile]不允许同时上传多个文件!/n");return false;}{boost::lock_guard<boost::mutex> l(g_ftp);m_bRun = true;m_bAbort = false;}//取待上传文件,文件大小FILE *file=_wfopen(bufFileName,L"rb");fseek(file,0,SEEK_END);m_filesize = ftell(file);fseek(file,0,SEEK_SET);memset(m_filename,0,sizeof(m_filename));wcsncpy(m_filename,bufFileName,sizeof(m_filename)/sizeof(wchar_t));////启动上传任务char * pURL = makeFullName(m_ip,bufFileName,uploadFilename);m_easyhandle = curl_easy_init();curl_easy_setopt(m_easyhandle, CURLOPT_URL, pURL); curl_easy_setopt(m_easyhandle, CURLOPT_READFUNCTION, CCurlFTP::readFromDisk); curl_easy_setopt(m_easyhandle, CURLOPT_READDATA , file); //文件指针传给readFromDisk!curl_easy_setopt(m_easyhandle, CURLOPT_UPLOAD , 1L); curl_easy_setopt(m_easyhandle, CURLOPT_INFILESIZE_LARGE, m_filesize);curl_easy_setopt(m_easyhandle, CURLOPT_USERPWD , m_usrpwd);curl_easy_setopt(m_easyhandle, CURLOPT_ERRORBUFFER, m_errbuf);CURLcode code = curl_easy_perform(m_easyhandle);curl_easy_cleanup(m_easyhandle);{boost::lock_guard<boost::mutex> l(g_ftp);fclose(file);m_bRun = false;m_bAbort = false;}bool bR = (code!=0)?false:true;if (m_call)m_call->done(bR);if (!bR)OutputDebugStringA(m_errbuf);return bR;}bool CCurlFTP::deleteFile(std::wstring fileName){std::string sCmd("DELE ");char buf[MAX_PATH];memset(buf,0,sizeof(buf));w2c(fileName.c_str(),buf,fileName.length()*2+1);sCmd = sCmd + buf;struct curl_slist *headers=NULL; /* init to NULL is important */headers = curl_slist_append(headers, sCmd.c_str());m_easyhandle = curl_easy_init();curl_easy_setopt(m_easyhandle, CURLOPT_URL, m_ip);curl_easy_setopt(m_easyhandle, CURLOPT_USERPWD , m_usrpwd);curl_easy_setopt(m_easyhandle, CURLOPT_ERRORBUFFER, m_errbuf);curl_easy_setopt(m_easyhandle, CURLOPT_QUOTE, headers);// curl_easy_setopt(easyhandle, CURLOPT_POSTQUOTE, headers); // 在数据传输之后操行删除操作CURLcode code = curl_easy_perform(m_easyhandle); /* transfer ftp data! */curl_slist_free_all(headers); /* free the header list */curl_easy_cleanup(m_easyhandle);bool bR = (code!=0)?false:true;if (!bR)OutputDebugStringA(m_errbuf);return bR;}bool CCurlFTP::isFileExist(wchar_t * filename){if(_waccess(filename, 0) == 0)return true;return false;}bool CCurlFTP::isFileRead(wchar_t * filename){if(_waccess(filename, 4) == 0)return true;return false;}void CCurlFTP::abort(){if(m_bRun){m_bAbort = true;}}char * CCurlFTP::makeFullName(char *ip,wchar_t * filename,wchar_t * uploadFilename){static char cR[_CF_BUF_SIZE_];int nPos = strlen(ip);std::wstring wsFN=filename;if(wsFN.find_last_of(L'//')!=-1)wsFN = wsFN.substr(wsFN.find_last_of(L'//')+1,wsFN.length());memset(cR,0,sizeof(cR));strncpy(cR,ip,sizeof(cR));cR[nPos]='/';//拼接字符串char buf[_CF_BUF_SIZE_];memset(buf,0,sizeof(buf));if (uploadFilename==NULL)w2c(filename,buf,wcslen(filename)*2+1);elsew2c(uploadFilename,buf,wcslen(uploadFilename)*2+1);strncpy((cR+nPos+1),buf,_CF_BUF_SIZE_-nPos);return cR;}char *CCurlFTP::w2c(const wchar_t *pwstr,char *pcstr, size_t len){int nlength=wcslen(pwstr);//获取转换后的长度int nbytes = WideCharToMultiByte( 0, // specify the code page used to perform the conversion0, // no special flags to handle unmapped characterspwstr, // wide character string to convertnlength, // the number of wide characters in that stringNULL, // no output buffer given, we just want to know how long it needs to be0,NULL, // no replacement character givenNULL ); // we don't want to know if a character didn't make it through the translation// make sure the buffer is big enough for this, making it larger if necessaryif(nbytes>len) nbytes=len;// 通过以上得到的结果,转换unicode 字符为ascii 字符WideCharToMultiByte( 0, // specify the code page used to perform the conversion0, // no special flags to handle unmapped characterspwstr, // wide character string to convertnlength, // the number of wide characters in that stringpcstr, // put the output ascii characters at the end of the buffernbytes, // there is at least this much space thereNULL, // no replacement character givenNULL );return pcstr ;}
|
|