利用http实现文件的上传和下载

摘要:
这样就可以利用这个库来实现http上传和下载了。不过在学这个库的接口之前,最好先了解下http,特别是GET和POST方法的区别,这两个方法前者涉及到对URL的查询,后者涉及到对URL的改写。并不能根据它们的名字直接理解,详情请看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 classHttpRecver {
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     boolrecv();
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::stringm_url;
32     std::stringm_savePath;
33     std::stringm_filename;
34     boolm_isValid;
35     boolm_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     returnm_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 boolHttpRecver::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     returnnWrite;
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

免责声明:文章转载自《利用http实现文件的上传和下载》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Linux磁盘管理及LVM讲解Centos7配置BIND开机自启动下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

nginx实战二

 nginx架构分析 1.nginx模块化 Nginx涉及到的模块分为核心模块、标准HTTP模块、可选HTTP模块、邮件服务模块以及第三方模块等五大类。 https://coding.net/u/aminglinux/p/nginx/git/blob/master/4z/module.md [root@centos-03 objs]# ls ngx_mo...

Yii2通过curl调用json-rpc接口

Yii2可以通过json-rpc为前端提供接口数据,通常情况睛会使用异步的形式调用接口,有时也会使用curl调用接口数据。 一、异步调用json-rpc接口 $.ajax({ type: 'POST', url: "http://localhost/index?r=test",...

微信开发笔记:获取用户openid,以及用户头像昵称等信息

微信开发的时候有一个很便利的途径来进行一个用户的一步注册登录,就是使用用户的微信信息来直接进行登陆,可以省去很多不必要的麻烦。那具体这些信息是如何来获取的呢? 首先呢,我们需要对微信进行一个授权,让微信页面有权限来读取我们的用户信息: $redirect_uri = urlencode($url); //设置授权页面,此处填写回调的授权页面地址 $scop...

PHP中获取远程文件的三种方法

1.file_get_contents <?php $url = 'http://www.xxx.com/'; $contents = file_get_contents($url); //如果出现中文乱码使用下面代码 //$getcontent = iconv(“gb2312″, “utf-8″,file_get_contents($url));...

influxdb简单使用

之前对influxdb有一个简单的了解和入门的使用,近期由于想使用influxdb做一点东西玩玩,又要捡起influxdb。本篇就针对influxdb的数据库、表的概念,增删改查操作、RESTful操作等做下总结。 一、influxdb与传统数据库的比较 库、表等比较: influxDB 传统数据库中的概念 database 数据库 meas...

libcurl进行HTTP GET获取JSON数据(转载)

转载:http://blog.csdn.net/vincent2610/article/details/68488365 #include <stdio.h> #include <iostream> #include <sstream> using namespacestd; size_t write_data(vo...