zoukankan      html  css  js  c++  java
  • 利用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

  • 相关阅读:
    public/private/protected的具体区别
    解决密码自动填充的问题
    tp导出excel
    好久没更了,确实太忙了--dedecms篇
    解决css的float父div没有高度
    随笔
    总结最近写的h5项目
    ajax删除当前行
    开发时常遇到的小问题
    js处理时间戳
  • 原文地址:https://www.cnblogs.com/foohack/p/4955392.html
Copyright © 2011-2022 走看看