libcurl 404检测

时间:2010-11-23 03:35:20

标签: c++

我在我的c ++程序中使用libcurl进行文件下载。如何检测请求是否为404,而不是写入文件?代码是:

    void GameImage::DownloadImage(string file_name) {
    string game_name;
    game_name = file_name.substr(file_name.find_last_of("/")+1);

    CURL *curl;
    FILE *fp;
    CURLcode res;
    string url = "http://site/"+game_name+".png";
    string outfilename = file_name+".png";
    cout<<"INFO; attempting to download "<<url<<"..."<<endl;
    curl = curl_easy_init();
    if (curl) {
        cout<<"INFO; downloading "<<url<<"..."<<endl;
        fp = fopen(outfilename.c_str(), "wb");
        cout<<"INFO; trying to open "<<outfilename<<" for file output"<<endl;
        if (fp != NULL) {
            curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, GameImage::WriteData);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
            curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
            curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
            res = curl_easy_perform(curl);

            long http_code = 0;
            curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);

            curl_easy_cleanup(curl);
            fclose(fp);
        }
        else {
            cout<<"GameImage::DownloadImage; Couldn't open output file"<<endl;
        }
    }
}

size_t GameImage::WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t written;
    written = fwrite(ptr, size, nmemb, stream);
    return written;
}

我可以在转移发生后删除404响应,但最好不保存响应。

2 个答案:

答案 0 :(得分:4)

您可以查看CURLE_HTTP_RETURNED_ERROR

如果CURLOPT_FAILONERROR设置为true并且HTTP服务器返回>= 400的错误代码,则会返回此信息。您无法获取特定的HTTP响应代码,但应该足以完成您想要的任务。

答案 1 :(得分:1)

我知道这是一篇旧帖子,但您所做的错误是您没有检查curl_easy_perform的返回值。设置CURLOPT_FAILONERROR不会使程序崩溃,而是通过命名为res的返回变量通知您错误。要摆脱空文件,你可以这样做:

void GameImage::DownloadImage(string file_name) {
    string game_name;
    game_name = file_name.substr(file_name.find_last_of("/")+1);

    CURL *curl;
    FILE *fp;
    CURLcode res;
    string url = "http://site/"+game_name+".png";
    string outfilename = file_name+".png";
    cout<<"INFO; attempting to download "<<url<<"..."<<endl;
    curl = curl_easy_init();
    if (curl) {
        cout<<"INFO; downloading "<<url<<"..."<<endl;
        fp = fopen(outfilename.c_str(), "wb");
        cout<<"INFO; trying to open "<<outfilename<<" for file output"<<endl;
        if (fp == NULL) {
            cout<<"GameImage::DownloadImage; Couldn't open output file"<<endl;
            curl_easy_cleanup(curl);
            return;
        }
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, GameImage::WriteData);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
        curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
        res = curl_easy_perform(curl);
        fclose(fp);

        if (res != CURLE_OK) {
            cout<<"GameImage::DownloadImage; Failed to download file"<<endl;
            remove(outfilename.c_str());
        }

        curl_easy_cleanup(curl);
    }
}

size_t GameImage::WriteData(void *ptr, size_t size, size_t nmemb, FILE *stream) {
    size_t written;
    written = fwrite(ptr, size, nmemb, stream);
    return written;
}