libcurl編譯使用,實現ftp功能
Libcurl實現ftp的下載,上傳功能。版本為curl-7.63.0
1、編譯vs2015
參考資料:https://blog.csdn.net/yaojingkao/article/details/53044361
2、libcurl傳輸進度參考:
https://blog.csdn.net/u012234115/article/details/83869486
3、libcurl使用方法參考:
https://www.cnblogs.com/mengfanrong/p/4581068.html
4、在搜尋資料的時候,應該注意libcurl版本的問題,不同的版本,用法可能不同。
官網下載:
解壓到本地,使用vs2015開啟解決方案:
選擇libcurl,DLL Release,32位,進行編譯
編譯完成後,生成的庫檔案libcurl.dll 和 libcurl.lib 在下面的目錄中
2、使用:vs2015新建測試工程:
需要libcurl的標頭檔案跟動態庫。
libcurl標頭檔案路徑:
將libcurl標頭檔案跟庫檔案,放到ftptest.sln解決方案下面
在ftptest.sln同級目錄下,新建include和lib目錄
將libcurl的標頭檔案拷貝到include目錄下
將libcurl的庫拷貝到lib目錄下目錄下
將libcurl標頭檔案加入到工程配置中:
將libcurl庫加入到工程配置中:
在工程中連線libcurl庫:
對libcurl進行c++封裝,測試,c++使用Qt
標頭檔案:
#ifndef FTPLIBCURL_H
#define FTPLIBCURL_H
#include "curl/curl.h"
#include "curl/easy.h"
#include <QObject>
class FtpLibCurl;
struct CustomProgress
{
curl_off_t lastruntime; /* type depends on version, see above */
CURL *curl;
FtpLibCurl* p;
};
class FtpLibCurl : public QObject
{
Q_OBJECT
public:
FtpLibCurl(QObject *parent);
~FtpLibCurl();
public:
void getProg(qulonglong);
void setFile(const QString&);
public slots:
void process();
void downFile();
signals:
void finished();
void error(QString err);
void ftp_prog(QString);
public:
struct CustomProgress prog;
private:
qulonglong m_fileSize;
QString m_s_percentage;
QString m_fileName;
};
#endif // FTPLIBCURL_H
Cpp檔案:
#include "FtpLibCurl.h"
//#define F_LOCAL_FILE "F:/1.jpg"
//#define F_REMOTE_URL "ftp://192.168.16.166:21//home/msj/1.jpg"
size_t f_read_callback(void *ptr, size_t size, size_t nmemb, void *stream) //回撥函式
{
curl_off_t nread;
size_t retcode = fread(ptr, size, nmemb, (FILE*)(stream));
nread = (curl_off_t)retcode;
return retcode;
}
// work for both download and upload
int progressCallback(void *p,
curl_off_t dltotal,
curl_off_t dlnow,
curl_off_t ultotal,
curl_off_t ulnow)
{
struct CustomProgress *progress = (struct CustomProgress *)p;
CURL *curl = progress->curl;
curl_off_t curtime = 0;
curl_easy_getinfo(curl, CURLINFO_TOTAL_TIME_T, &curtime);
/* under certain circumstances it may be desirable for certain functionality
to only run every N seconds, in order to do this the transaction time can
be used */
if ((curtime - progress->lastruntime) >= 3000000)
{
progress->lastruntime = curtime;
//printf("TOTAL TIME: %f \n", curtime);
}
// do something to display the progress
//printf("UP: %ld bytes of %ld bytes, DOWN: %ld bytes of %ld bytes \n", ulnow, ultotal, dlnow, dltotal);
if (ultotal)
{
//printf("UP progress: %0.2f\n", float(ulnow / ultotal));
progress->p->getProg(ulnow);
}
if (dltotal)
{
//("DOWN progress: %0.2f\n", float(dlnow / dltotal));
}
return 0;
}
FtpLibCurl::FtpLibCurl(QObject *parent)
: QObject(parent)
{
prog = {0};
m_s_percentage = QString("0%");
m_fileName.clear();
}
FtpLibCurl::~FtpLibCurl()
{
}
void FtpLibCurl::process()
{
CURL *pCurlhandle;
CURLcode res;
FILE *hd_src;
struct stat file_info;
curl_off_t fsize;
QByteArray ba = m_fileName.toLocal8Bit();
const char *c_str = ba.constData();
/*1. 獲取待上傳檔案的大小 */
if (stat(c_str, &file_info)) {
printf("Couldnt open '%s': %s\n", c_str, strerror(errno));
emit error(QString("local file not exist"));
return;
}
fsize = (curl_off_t)file_info.st_size;
m_fileSize = fsize;
/*2. 獲取待上傳檔案的描寫敘述符 */
hd_src = fopen(c_str, "rb");
/*3. 初始化全部可能的呼叫*/
curl_global_init(CURL_GLOBAL_ALL);
/*4. 建立一個curlhandle*/
pCurlhandle = curl_easy_init();
if (pCurlhandle)
{
curl_easy_setopt(pCurlhandle, CURLOPT_USERPWD, "msj:msj");
/*5.設定一個回撥函式 */
curl_easy_setopt(pCurlhandle, CURLOPT_READFUNCTION, f_read_callback);
/*6.使能上傳標誌位 */
curl_easy_setopt(pCurlhandle, CURLOPT_UPLOAD, 1L);
/*7.指定ftpserver的url */
QStringList path_list = m_fileName.split('/');
QString tmp_url = "ftp://192.168.16.166:21//home/xx/" + path_list.last();
QByteArray url_ba = tmp_url.toLocal8Bit();
const char *url_str = url_ba.constData();
curl_easy_setopt(pCurlhandle, CURLOPT_URL, url_str);
/*8.指定須要上傳的檔案 */
curl_easy_setopt(pCurlhandle, CURLOPT_READDATA, hd_src);
/*9.設定待上傳檔案的大小,這個大小是上面獲取到的注意:當引數
為CURLOPT_INFILESIZE_LARGE的時候。size型別應該是curl_off_t的,
當引數為CURLOPT_INFILESIZE的時候size應該是long型別的*/
curl_easy_setopt(pCurlhandle, CURLOPT_INFILESIZE_LARGE,
(curl_off_t)fsize);
// set upload progress
curl_easy_setopt(pCurlhandle, CURLOPT_XFERINFOFUNCTION, progressCallback);
curl_easy_setopt(pCurlhandle, CURLOPT_XFERINFODATA, &prog);
prog.p = this;
curl_easy_setopt(pCurlhandle, CURLOPT_NOPROGRESS, 0);
/*10. 開始執行我們上述設定的方法*/
res = curl_easy_perform(pCurlhandle);
/*11. 檢查是否執行成功 */
if (res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
emit error(QString(curl_easy_strerror(res)));
}
/*12. 關閉pCurlhandle*/
curl_easy_cleanup(pCurlhandle);
}
fclose(hd_src); /* close the local file */
/*13. 清除全部可能的呼叫*/
curl_global_cleanup();
emit finished();
}
void FtpLibCurl::getProg(qulonglong v)
{
int int_percentage = (v / m_fileSize)*100;
QString tmp_percentage = QString::number(int_percentage) + "%";
if (m_s_percentage!= tmp_percentage)
{
m_s_percentage = tmp_percentage;
emit ftp_prog(tmp_percentage);
}
}
void FtpLibCurl::downFile()
{
}
void FtpLibCurl::setFile(const QString& s)
{
m_fileName = s;
}
測試程式碼:
QThread *thread = new QThread();
FtpLibCurl *worker = new FtpLibCurl(nullptr);
worker->setFile(QString("F:/1.jpg"));
worker->moveToThread(thread);
// 錯誤處理
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
// 處理資料
connect(thread, SIGNAL(started()), worker, SLOT(process()));
// 退出、刪除
connect(worker, SIGNAL(error(QString)), this, SLOT(ftp_error(QString)));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
// 啟動執行緒
thread->start();