Skip to content

Instantly share code, notes, and snippets.

@zno5
Last active August 21, 2016 10:48
Show Gist options
  • Save zno5/0f86fa2b4725b78e8d39987be2946e22 to your computer and use it in GitHub Desktop.
Save zno5/0f86fa2b4725b78e8d39987be2946e22 to your computer and use it in GitHub Desktop.
Download a file with curl 7.43.0
#include <cstdint>
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
#include <cassert>
#include <curl/curl.h>
/*
first of all, initialize curl lib.
in main function, call it.
curl_global_init(CURL_GLOBAL_ALL);
call clean up function on program termination
curl_global_cleanup();
*/
////////////////////////////////////////////////////////////////////////////////
class CHttpDownload
{
public:
CHttpDownload() : m_curl(nullptr)
{
}
~CHttpDownload();
bool Initialize(const std::string & url, const std::string fileName = "");
bool Run();
auto & GetData() const
{
return m_buffer;
}
private:
static size_t WriteBufferCallback(
char * ptr,
size_t size,
size_t nmemb,
void * userdata
);
private:
CURL * m_curl;
std::vector<uint8_t> m_buffer;
std::string m_fileName;
std::ofstream m_file;
};
////////////////////////////////////////////////////////////////////////////////
CHttpDownload::~CHttpDownload()
{
curl_easy_cleanup(m_curl);
if (m_file.is_open())
{
m_file.close();
}
}
////////////////////////////////////////////////////////////////////////////////
bool CHttpDownload::Initialize(
const std::string & url,
const std::string fileName
)
{
m_fileName = fileName;
m_curl = curl_easy_init();
if (!m_curl)
{
return false;
}
if (curl_easy_setopt(m_curl, CURLOPT_URL, url.c_str()) != CURLE_OK)
{
return false;
}
if (curl_easy_setopt(m_curl, CURLOPT_SSL_VERIFYPEER, 0L) != CURLE_OK)
{
return false;
}
if (curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, 30) != CURLE_OK)
{
return false;
}
if (curl_easy_setopt(m_curl, CURLOPT_CONNECTTIMEOUT, 30) != CURLE_OK)
{
return false;
}
auto callback = &CHttpDownload::WriteBufferCallback;
if (curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, callback) != CURLE_OK)
{
return false;
}
auto data = static_cast<void *>(this);
if (curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, data) != CURLE_OK)
{
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
bool CHttpDownload::Run()
{
assert(m_curl);
if (!m_curl)
{
return false;
}
if (!m_fileName.empty())
{
m_file.open(
m_fileName,
std::ios::out | std::ios::trunc | std::ios::binary
);
}
auto code = curl_easy_perform(m_curl);
if (m_file.is_open())
{
m_file.close();
}
if (CURLE_OK != code)
{
std::cout << curl_easy_strerror(code) << std::endl;
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////
size_t CHttpDownload::WriteBufferCallback(
char * ptr,
size_t size,
size_t nmemb,
void * userdata
)
{
assert(1 == size);
auto bytes = size * nmemb;
auto http = static_cast<CHttpDownload *>(userdata);
if (http->m_file.is_open())
{
http->m_file.write(ptr, bytes);
return bytes;
}
auto & buffer = http->m_buffer;
auto bufferSize = buffer.size();
buffer.resize(bufferSize + bytes);
std::copy(ptr, ptr + bytes, buffer.begin() + bufferSize);
return bytes;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment