利用http實現文件的上傳和下載


其他語言都比較方便,使用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
View Code

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 }
View Code

 

 

 

 

 

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM