在收到初始请求的响应后发送后续的curl请求

  • 本文关键字:请求 curl 响应 c++ libcurl pixabay
  • 更新时间 :
  • 英文 :


在我写细节之前,这是我想要实现的。

  1. 在pixabay上搜索一些图片(在本例中搜索黄色的花)
  2. 当我发布这个查询,我会得到json数组与图像的细节。
  3. 解析数据并存储数组数据
  4. 现在发送后续curl请求来检索/下载使用数组数据中存在的url的图像。

当前代码:

我能够实现1,2,3。我所做的第三个实现(截至目前)是将数据本地存储在文件中并解析它。

我在第4点卡住了。

从数组data中取出一个元素:

"hits":[
{
"id":2295434,
"pageURL":"https://pixabay.com/photos/spring-bird-bird-tit-spring-blue-2295434/",
"type":"photo",
"tags":"spring bird, bird, tit",
"previewURL":"https://cdn.pixabay.com/photo/2017/05/08/13/15/spring-bird-2295434_150.jpg",
"previewWidth":150,
"previewHeight":99,
"webformatURL":"https://pixabay.com/get/gc323739b5570ab1afac9cff34f0ed431beffcf004e0660fcaff96a7b1780933e31c982b26cdb3234c4a757a9e7e8b824bda6059340ead3c6b755f1265f7ace52_640.jpg",
"webformatWidth":640,
"webformatHeight":426,
"largeImageURL":"https://pixabay.com/get/g58a377c4cffe13bffd15cb7b455ecec08329352a443689296c5f15565b3a7f11bcd5ec6e4d2945bb3d32b2a63ee33d6c9a9925119944d128cab4bca663f87620_1280.jpg",
"imageWidth":5363,
"imageHeight":3575,
"imageSize":2938651,
"views":488125,
"downloads":261832,
"collections":1911,
"likes":1846,
"comments":221,
"user_id":334088,
"user":"JillWellington",
"userImageURL":"https://cdn.pixabay.com/user/2018/06/27/01-23-02-27_250x250.jpg"
}
]

main.cc

#include "baseurihandler/base_uri_handler_pixabay.h"
#include "json_parser.h"
#include "download_image.h"
#include <stdio.h>
#include <iostream>
#include <curl/curl.h>
#include <iostream>
#include <chrono>
#include <string>
#include <thread>
#include <vector>
void JsonParser();
int main() {
CURL *curl;
CURLcode res;
std::vector<std::pair<std::string, std::string>> query_param;
query_param.push_back(std::make_pair("q", "yellow+flowers"));
query_param.push_back(std::make_pair("image_type", "photo"));
std::string s;
baseuri::PixabayURIHandler pixabay_uri_handler;
pixabay_uri_handler.SetQueryParameters(query_param);
//auto str = pixabay_uri_handler.GetURI();
auto str = std::string("https://pixabay.com/api/?key=xxxxxxx-xxxxxxxxxxx&q=yellow+flowers&image_type=photo");
std::cout << str << std::endl;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, str.c_str());
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, baseuri::PixabayURIHandler::CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pixabay_uri_handler);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %sn",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
//std::cout << pixabay_uri_handler.GetResultJsonString() << std::endl;
std::cout << "calling jsonparser.. " << std::endl;
JsonParser(); //This will return vec of URLs - TBD
char *jpg_test = "https://pixabay.com/get/g58a377c4cffe13bffd15cb7b455ecec08329352a443689296c5f15565b3a7f11bcd5ec6e4d2945bb3d32b2a63ee33d6c9a9925119944d128cab4bca663f87620_1280.jpg";
if (!download_jpeg(jpg_test))
{
printf("!! Failed to download file!n" );
return -1;
}
return 0;
}

download_jpeg:

的实现
#include <stdio.h>
#include <curl/curl.h>
size_t callbackfunction(void *ptr, size_t size, size_t nmemb, void* userdata)
{
FILE* stream = (FILE*)userdata;
if (!stream)
{
printf("!!! No streamn");
return 0;
}
size_t written = fwrite((FILE*)ptr, size, nmemb, stream);
return written;
}
bool download_jpeg(char* url)
{
FILE* fp = fopen("out.jpg", "wb");
if (!fp)
{
printf("!!! Failed to create file on the diskn");
return false;
}
CURL* curlCtx = curl_easy_init();
curl_easy_setopt(curlCtx, CURLOPT_URL, url);
curl_easy_setopt(curlCtx, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curlCtx, CURLOPT_WRITEFUNCTION, callbackfunction);
curl_easy_setopt(curlCtx, CURLOPT_FOLLOWLOCATION, 1);
CURLcode rc = curl_easy_perform(curlCtx);
if (rc)
{
printf("!!! Failed to download: %sn", url);
return false;
}
long res_code = 0;
curl_easy_getinfo(curlCtx, CURLINFO_RESPONSE_CODE, &res_code);
if (!((res_code == 200 || res_code == 201) && rc != CURLE_ABORTED_BY_CALLBACK))
{
printf("!!! Response code: %dn", res_code);
return false;
}
curl_easy_cleanup(curlCtx);
fclose(fp);
return true;
}

形成下载图像的后续URL的正确方式是什么?而不是直接发送largeImageURL对于download_jpeg(),我尝试将api key作为查询参数与largeImageURL值一起添加,但没有帮助-收到400个响应代码。

pixabay文档中没有任何帮助。

如果没有特殊的附加操作,curl easy句柄不会共享会话状态。但是每个单独的会话都保留一个会话状态,并且可以重用它,直到curl_easy_cleanup()被调用。您在download_jpeg中使用了另一个curl简单句柄-这就是错误"此URL无效或已过期"的原因。

最简单的解决方法是重用curl的easy句柄。

bool download_jpeg(CURL* curl, const char* url)
{
FILE* fp = fopen("out.jpg", "wb");
if (!fp)
{
printf("!!! Failed to create file on the diskn");
return false;
}
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callbackfunction);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
CURLcode rc = curl_easy_perform(curl);
if (rc)
{
printf("!!! Failed to download: %sn", url);
return false;
}
long res_code = 0;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &res_code);
if (!((res_code == 200 || res_code == 201) && rc != CURLE_ABORTED_BY_CALLBACK))
{
printf("!!! Response code: %dn", res_code);
return false;
}
fclose(fp);
return true;
}
int main() {
CURL *curl;
CURLcode res;
std::vector<std::pair<std::string, std::string>> query_param;
query_param.push_back(std::make_pair("q", "yellow+flowers"));
query_param.push_back(std::make_pair("image_type", "photo"));
std::string s;
baseuri::PixabayURIHandler pixabay_uri_handler;
pixabay_uri_handler.SetQueryParameters(query_param);
//auto str = pixabay_uri_handler.GetURI();
auto str = std::string("https://pixabay.com/api/?key=xxxxxxx-xxxxxxxxxxx&q=yellow+flowers&image_type=photo");
std::cout << str << std::endl;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "");
curl_easy_setopt(curl, CURLOPT_URL, str.c_str());
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, baseuri::PixabayURIHandler::CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &pixabay_uri_handler);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %sn",
curl_easy_strerror(res));
}
//std::cout << pixabay_uri_handler.GetResultJsonString() << std::endl;
std::cout << "calling jsonparser.. " << std::endl;
JsonParser(); //This will return vec of URLs - TBD
const char* jpg_test = "https://pixabay.com/get/g58a377c4cffe13bffd15cb7b455ecec08329352a443689296c5f15565b3a7f11bcd5ec6e4d2945bb3d32b2a63ee33d6c9a9925119944d128cab4bca663f87620_1280.jpg";
const bool rv = download_jpeg(curl, jpg_test);
if (!rv)
printf("!! Failed to download file!n" );
/* always cleanup */
curl_easy_cleanup(curl);
return rv ? -1 : 0;
}

download_jpeg()存在问题:

  • curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
    

    必须通过长1L

    curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    
  • 内存泄漏-curl_easy_cleanup(curlCtx);不被调用,如果错误发生,由于早期return。新版本没有创建新的curl easy处理程序,因此没有内存泄漏。

main已更新:

  • curl_easy_setopt(curl, CURLOPT_COOKIEFILE, "")激活cookie引擎
  • curl句柄传递给download_jpeg并在那里重用。
  • curl_easy_cleanup(curl);被移到最后
  • 字符串在c++中是常量字符数组,因此必须使用const char* jpg_test = "";

如果您需要在单个会话中使用多个curl轻松句柄,请遵循手动共享轻松句柄,或者使用单个curl多句柄与多个curl轻松句柄。