开发者

libcurl 404 detection

I'm doing a file download with libcurl in my c++ program. How can i detect if the request is a 404, and not do the file write? The code is:

    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, &h开发者_开发知识库ttp_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;
}

I can delete the 404 response after the transfer occurs, but it would be good to not even save the response.


You can check against CURLE_HTTP_RETURNED_ERROR

This is returned if CURLOPT_FAILONERROR is set to true and the HTTP server returns an error code that is >= 400. You can't grab the specific HTTP response code, but should be enough to accomplish what you want.


I know this is an old post, but the error you're doing is that you're not checking the return value of curl_easy_perform. Setting CURLOPT_FAILONERROR will not crash the program, instead, it will notify you of the error through the return variable you named res. To get rid of the empty file, you could do something like this:

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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜