其他語言都比較方便,使用http上傳。但是C++這樣就差點,不過還好,Linux下有個curl的命令行工具,這是一個開源項目,底下有個子項目是libcurl,curl就是調用這個API實現的一系列ftp,http等上傳下載的功能,這個庫功能還是挺多的。支持的協議也多。這樣就可以利用這個庫來實現http上傳和下載了。
當然這個庫的API有兩種接口,一種是esay的-------同步阻塞模式。另一種是Multi的,我沒研究它,以下用的都是easy的接口,來寫的樣例代碼。
不過在學這個庫的接口之前,最好先了解下http,特別是GET和POST方法的區別,這兩個方法前者涉及到對URL的查詢,后者涉及到對URL的改寫。當然GET和POST都可以向server傳輸數據。並不能根據它們的名字直接理解,詳情請看http協議吧。我找了兩個不錯的博客連接,來理解http相關的內容,非常不錯,寫得很好:
http://www.cnblogs.com/devil-91/archive/2012/05/11/2495266.html
http://www.cnblogs.com/hyddd/archive/2009/03/31/1426026.html
文件上傳類:
H文件:
#ifndef QCURL_SENDER_H
#define QCURL_SENDER_H
#include <string>
#include <curl/curl.h>
class CurlSender{
public:
CurlSender();
~CurlSender();
bool isValid() const;
void setUrl(const std::string& url);
bool send(const std::string &file);
private:
std::string getFileNameFromPath(const std::string& path);
private:
CURL* m_hCurl;
std::string m_url;
bool m_isValid;
};
#endif
.cpp文件
#include "QCurlSender.h"
CurlSender::CurlSender():
m_hCurl(nullptr), m_isValid(false)
{
curl_global_init(CURL_GLOBAL_ALL);
m_hCurl = curl_easy_init();
if (m_hCurl)
{
m_isValid = true;
}
}
CurlSender::~CurlSender()
{
if (m_hCurl)
{
curl_easy_cleanup(m_hCurl);
}
curl_global_cleanup();
}
bool CurlSender::isValid() const
{
return m_isValid;
}
void CurlSender::setUrl(const std::string& url)
{
m_url = url;
}
bool CurlSender::send(const std::string &file)
{
curl_slist* pOptionList = NULL;
pOptionList = curl_slist_append(pOptionList, "Expect:");
curl_easy_setopt(m_hCurl, CURLOPT_HTTPHEADER, pOptionList);
curl_httppost* pFormPost = NULL;
curl_httppost* pLastElem = NULL;
//上傳文件,指定本地文件完整路徑
curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "sendfile",
CURLFORM_FILE, file.c_str(), CURLFORM_CONTENTTYPE,
"application/octet-stream", CURLFORM_END);
curl_formadd(&pFormPost, &pLastElem,
CURLFORM_COPYNAME, "filename",
CURLFORM_COPYCONTENTS, getFileNameFromPath(file).c_str(),
CURLFORM_END);
//不加一個結束的hfs服務端無法寫入文件,一般不存在這種問題,這里加入只是為了測試.
curl_formadd(&pFormPost, &pLastElem, CURLFORM_COPYNAME, "end", CURLFORM_COPYCONTENTS, "end", CURLFORM_END);
curl_easy_setopt(m_hCurl, CURLOPT_HTTPPOST, pFormPost);
curl_easy_setopt(m_hCurl, CURLOPT_URL, m_url.c_str());
CURLcode res = curl_easy_perform(m_hCurl);
if (res != CURLE_OK)
{
return false;
}
curl_formfree(pFormPost);
return true;
}
std::string CurlSender::getFileNameFromPath(const std::string& path)
{
return path.substr(path.find_last_of("/\\") + 1);
}
http下載類:
H文件:
1 #ifndef TASK_HTTP_RECVER_H 2 #define TASK_HTTP_RECVER_H 3 4 #include <curl/curl.h> 5 #include <string> 6 #include <cstdio> 7 8 class HttpRecver { 9 10 11 public: 12 HttpRecver(); 13 ~HttpRecver(); 14 15 bool isValid() const; 16 void setUrl(const std::string& url); 17 void setSavePath(const std::string &path); 18 19 20 21 22 private: 23 bool recv(); 24 //下載回調函數 25 static size_t DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam); 26 std::string getFileNameFromPath(const std::string& path); 27 28 private: 29 FILE *m_fp; 30 CURL* m_hCurl; 31 std::string m_url; 32 std::string m_savePath; 33 std::string m_filename; 34 bool m_isValid; 35 bool m_bReady; 36 37 }; 38 39 #endif
cpp文件:
1 #include "TaskHttpRecver.h" 2 3 HttpRecver::HttpRecver() : 4 m_isValid(false), m_hCurl(nullptr), m_fp(nullptr) 5 { 6 7 LOG_(LOGID_DEBUG, LOG_F("Entry HttpRecver()")); 8 9 curl_global_init(CURL_GLOBAL_ALL); 10 m_hCurl = curl_easy_init(); 11 12 if (m_hCurl) 13 { 14 m_isValid = true; 15 } 16 17 LOG_(LOGID_DEBUG, LOG_F("Entry HttpRecver()")); 18 } 19 20 HttpRecver::~HttpRecver() 21 { 22 LOG_(LOGID_DEBUG, LOG_F("Entry ~HttpRecver()")); 23 24 if (m_hCurl) 25 { 26 curl_easy_cleanup(m_hCurl); 27 } 28 29 curl_global_cleanup(); 30 31 LOG_(LOGID_DEBUG, LOG_F("Leave ~HttpRecver()")); 32 } 33 34 bool HttpRecver::isValid() const 35 { 36 return m_isValid; 37 } 38 39 void HttpRecver::setUrl(const std::string& url) 40 { 41 m_url = url; 42 m_filename = getFileNameFromPath(m_url); 43 } 44 45 void HttpRecver::setSavePath(const std::string &path) 46 { 47 m_savePath = path; 48 } 49 50 std::string HttpRecver::getFileNameFromPath(const std::string& path) 51 { 52 return path.substr(path.find_last_of("/\\") + 1); 53 } 54 55 bool HttpRecver::recv() 56 { 57 curl_easy_setopt(m_hCurl, CURLOPT_URL, m_url.c_str()); 58 59 std::string filePath = m_savePath + m_filename; 60 61 m_fp = fopen(filePath.c_str(), "wb"); 62 63 if (!m_fp) 64 { 65 return false; 66 } 67 68 //設置接收數據的回調 69 curl_easy_setopt(m_hCurl, CURLOPT_WRITEFUNCTION, DownloadCallback); 70 curl_easy_setopt(m_hCurl, CURLOPT_WRITEDATA, m_fp); 71 curl_easy_setopt(m_hCurl, CURLOPT_MAXREDIRS, 5); 72 curl_easy_setopt(m_hCurl, CURLOPT_FOLLOWLOCATION, 1); 73 74 CURLcode retcCode = curl_easy_perform(m_hCurl); 75 76 if (retcCode != CURLE_OK) 77 { 78 79 fclose(m_fp); 80 m_fp = nullptr; 81 return false; 82 } 83 84 fclose(m_fp); 85 m_fp = nullptr; 86 87 return true; 88 } 89 90 size_t HttpRecver::DownloadCallback(void* pBuffer, size_t nSize, size_t nMemByte, void* pParam) 91 { 92 FILE* fp = (FILE*)pParam; 93 size_t nWrite = fwrite(pBuffer, nSize, nMemByte, fp); 94 95 return nWrite; 96 }
references:
http://www.cnblogs.com/cswuyg/archive/2013/07/11/3185164.html
http://www.cnblogs.com/lidabo/p/4159574.html
http://blog.csdn.net/breaksoftware/article/details/45874197
http://stackoverflow.com/questions/8520560/get-a-file-name-from-a-path
http://blog.csdn.net/mfcing/article/details/43051865
http://blog.csdn.net/infoworld/article/details/46646933
