VC实现上传文件到FTP服务器

本文介绍了一种使用C++实现FTP文件上传和删除功能的方法,包括设置FTP服务器地址、上传文件及取消上传任务等操作。详细解释了如何通过自定义类和回调函数来实现同步上传文件到FTP服务器的过程,以及如何删除指定的FTP文件。

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

使用示例代码片段

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 here m_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.youkuaiyun.com/JGood/archive/2009/11/08/4787670.aspx 索引关键词:VC实现上传文件到Windows FTP服务器 */ #define _CF_BUF_SIZE_ 256 //下面是回调Class class IUploadEvent { public: //回调函数只是完成变量之间赋值,必须马上返回控制权给CCurlFTP实例所在的线程 //通知当前进度,取值范围0~1 virtual void setProgress(float fV)=0; //通知上传操作完成,true成功,false失败! virtual void done(bool bSuccess)=0; }; //下面是实现上传功能的Class class 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; } //删除指定的文件,删除成功返回true bool 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: static curl_off_t m_filesize; static bool m_bAbort; //当前是否在执行上传操作,若是m_bRun=true,elsewise the variable m_bRun is false! static bool 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 upload size_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*1024 nRead = 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); else w2c(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 conversion 0, // no special flags to handle unmapped characters pwstr, // wide character string to convert nlength, // the number of wide characters in that string NULL, // no output buffer given, we just want to know how long it needs to be 0, NULL, // no replacement character given NULL ); // 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 necessary if(nbytes>len) nbytes=len; // 通过以上得到的结果,转换unicode 字符为ascii 字符 WideCharToMultiByte( 0, // specify the code page used to perform the conversion 0, // no special flags to handle unmapped characters pwstr, // wide character string to convert nlength, // the number of wide characters in that string pcstr, // put the output ascii characters at the end of the buffer nbytes, // there is at least this much space there NULL, // no replacement character given NULL ); return pcstr ; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值