Я создал эту самую базовую c оболочку для завитков и могу загрузить с нее html страницы, но у меня возникает проблема, когда я пытаюсь получить изображения (не пробовал другие файлы).
class BasicCurlWrapper
{
CURL* m_curlHandle{ nullptr };
std::string m_current_url{};
std::string m_destinationFilePath{};
std::ofstream m_outputFile{};
std::ios_base::openmode m_fileOpenMode{ std::ios::out };
bool m_verbose{ false };
public:
BasicCurlWrapper()
{
m_curlHandle = curl_easy_init();
}
~BasicCurlWrapper()
{
curl_easy_cleanup(m_curlHandle);
//curl_global_cleanup();
}
void downloadUrl(const std::string& url, const std::string& destination, std::ios_base::openmode openmode = std::ios::out)
{
if (m_outputFile.is_open()) {
m_outputFile.close();
}
m_current_url = url;
m_destinationFilePath = destination;
m_fileOpenMode = openmode;
char errbuf[CURL_ERROR_SIZE] = { 0 };
curl_easy_setopt(m_curlHandle, CURLOPT_URL, url.data());
curl_easy_setopt(m_curlHandle, CURLOPT_VERBOSE, m_verbose ? 1L : 0L); //Switch on full protocol/debug output while testing
curl_easy_setopt(m_curlHandle, CURLOPT_NOPROGRESS, 1L); //disable progress meter, set to 0L to enable it
curl_easy_setopt(m_curlHandle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(m_curlHandle, CURLOPT_USERAGENT, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36");
curl_easy_setopt(m_curlHandle, CURLOPT_WRITEFUNCTION, BasicCurlWrapper::write_data);
curl_easy_setopt(m_curlHandle, CURLOPT_WRITEDATA, this);
curl_easy_setopt(m_curlHandle, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(m_curlHandle, CURLOPT_ERRORBUFFER, errbuf);
//curl_easy_setopt(m_curlHandle, CURLOPT_ACCEPT_ENCODING, "");
//curl_easy_setopt(m_curlHandle, CURLOPT_SSLCERT, "C:/msys64/mingw64/ssl/certs/ca-bundle.crt");
auto res = curl_easy_perform(m_curlHandle);
if (m_outputFile.is_open()) {
m_outputFile.close();
}
if (res == CURLE_OK) {
std::cout << "Downloaded file\n";
} else {
std::cout << "ERROR: " << curl_easy_strerror(res) << '\n' << errbuf << '\n';
}
}
void setVerbose(bool cond)
{
m_verbose = cond;
}
//https://curl.haxx.se/mail/lib-2008-09/0250.html
static std::size_t write_data(const char* ptr, const std::size_t size, const std::size_t nmemb, void* classIntance)
{
if (nmemb > 0) {
static_cast<BasicCurlWrapper*>(classIntance)->writeToFile(ptr, nmemb);
}
return nmemb;
}
private:
void writeToFile(const char* ptr, const std::size_t nmemb)
{
if (!m_outputFile.is_open()) {
m_outputFile.open(m_destinationFilePath, m_fileOpenMode);
}
if (m_outputFile.is_open()) {
std::cout << "Writing data amount: " << nmemb << '\n';
m_outputFile.write(ptr, nmemb);
} else {
auto errorMsg{ std::string{"Unable to open file: " + m_destinationFilePath } };
throw std::runtime_error{ errorMsg };
}
}
};
Так что я использую это так:
BasicCurlWrapper cr;
cr.setVerbose(true);
cr.downloadUrl("https://icons.iconarchive.com/icons/google/noto-emoji-activities/512/52730-soccer-ball-icon.png", "ball.png", std::ios::out | std::ios::binary);
Это что-то загружает:
‰PNG
¾M&S»Á€>öÝÀKþ駟ªC²²²Ð½{wÕ5–-[†…*7Þx½zõ¢C˜ž––L›6
555ŠÛŽ1þ³ºÂr'Å·Íê>ð^ùpAmèÀŽãœ.—«–@èEÀŒ±yJÛ)©éâàÔóÚÄ™ÄA]]¦NŠ¦æfÅ÷uÍ5Tò—+Ö[‡¾òŠªúÕ×^CvŸ>gtò'É·ý›œü¹QYñÇÝér¹þmöçpÁð^¯w€AJÛFâR€–tîܹ=Ï cä`íÚµX»vâëÙív,X°€ªþa…$I¸ë®»T•¾ðÂqß}÷µÏàÛÖä:„ŠŠ
Šbª$€Ðÿ.
И хотя он начинается с PNG, это недопустимо PNG, а также оригинальный файл 39 КБ. Нужно ли отправлять дополнительные заголовки или что-то еще? Я хотел бы иметь возможность загрузить любой указанный файл.
Я использовал vcpkg
для получения libcurl:
curl:x64-windows 7.68.0
РЕДАКТИРОВАТЬ:
Я обновил код, чтобы отразить ответ @Some программиста, чувак, который я сейчас использую write
для вывода данных в файл. Это исправлено для примера изображения, которое я использовал.
Проблема, с которой я столкнулся, связана с другим изображением, которое я пытаюсь загрузить.
cr.downloadUrl("https://v217.mangabeast.com/manga/Onepunch-Man/0130-007.png", "image.png", std::ios::out | std::ios::binary);
Файл image.png
теперь содержит текст :
error code: 1010
Я могу загрузить это изображение, просто используя команду:
curl -O <url>
Так что я ничего не передаю с помощью команды curl, так что мне нужно передать в libcurl ??
Вот результат запроса:
* STATE: INIT => CONNECT handle 0x24781b66728; line 1605 (connection #-5000)
* Added connection 0. The cache now contains 1 members
* STATE: CONNECT => WAITRESOLVE handle 0x24781b66728; line 1646 (connection #0)
* Trying 104.31.15.158:443...
* TCP_NODELAY set
* STATE: WAITRESOLVE => WAITCONNECT handle 0x24781b66728; line 1725 (connection #0)
* Connected to v217.mangabeast.com (104.31.15.158) port 443 (#0)
* STATE: WAITCONNECT => SENDPROTOCONNECT handle 0x24781b66728; line 1781 (connection #0)
* Marked for [keep alive]: HTTP default
* schannel: SSL/TLS connection with v217.mangabeast.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 184 bytes...
* schannel: sent initial handshake data: sent 184 bytes
* schannel: SSL/TLS connection with v217.mangabeast.com port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* STATE: SENDPROTOCONNECT => PROTOCONNECT handle 0x24781b66728; line 1796 (connection #0)
* schannel: SSL/TLS connection with v217.mangabeast.com port 443 (step 2/3)
* schannel: encrypted data got 2709
* schannel: encrypted data buffer: offset 2709 length 4096
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with v217.mangabeast.com port 443 (step 2/3)
* schannel: encrypted data got 258
* schannel: encrypted data buffer: offset 258 length 4096
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with v217.mangabeast.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
* STATE: PROTOCONNECT => DO handle 0x24781b66728; line 1815 (connection #0)
> GET /manga/Onepunch-Man/0130-007.png HTTP/1.1
Host: v217.mangabeast.com
User-Agent: User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36
Accept: */*
* STATE: DO => DO_DONE handle 0x24781b66728; line 1870 (connection #0)
* STATE: DO_DONE => PERFORM handle 0x24781b66728; line 1991 (connection #0)
* schannel: client wants to read 16384 bytes
* schannel: encdata_buffer resized 17408
* schannel: encrypted data buffer: offset 0 length 17408
* schannel: encrypted data got 674
* schannel: encrypted data buffer: offset 674 length 17408
* schannel: decrypted data length: 611
* schannel: decrypted data added: 611
* schannel: decrypted cached: offset 611 length 16384
* schannel: encrypted data length: 34
* schannel: encrypted cached: offset 34 length 17408
* schannel: decrypted data length: 5
EDIT2:
Теперь я добавил проверку ошибок, а также ошибку по ошибке. Я получил следующее:
ERROR: HTTP response code said error
The requested URL returned error: 403 Forbidden
Я не понимаю, как я получаю 403
, так как использование cURL через командную строку дает мне изображение.
EDIT 3:
Только что заметил, что строка пользовательского агента имеет User-Agent:
, после ввода действительного пользовательского агента я получил файл!