Search code examples
c++c++11visual-studio-2017poco-libraries

Problem downloading an image with Poco C++


I am trying to download an image from a url link via Poco in C++ but has encountered a problem with it. It always catches a NoMessageException whenever the code below is ran (the receiveResponse part). The 2 code blocks below is referred from: https://www.codeproject.com/articles/252566/learning-poco-get-with-http and C++ Http Request with POCO

Example 1

   try
        {
        URI uri("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
        std::string path(uri.getPathAndQuery());
        if (path.empty()) path = "/";
        HTTPClientSession session(uri.getHost(), uri.getPort());
        HTTPRequest request(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
        HTTPResponse response;

        bool isSuccess = false;
        session.sendRequest(request);
        std::istream& rs = session.receiveResponse(response);
        std::cout << response.getStatus() << " " << response.getReason() << std::endl;
        if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED)
        {
            std::ofstream ofs("Poco_banner.png",std::fstream::binary); 
            StreamCopier::copyStream(rs, ofs);
            isSuccess = true;
        }
        else
        {
            //it went wrong ?
            isSuccess = false;
        }

        if (!isSuccess)
        {
            std::cerr << "Invalid username or password" << std::endl;
            return;
        } else
        {
            cout << "done download" << endl;
        }
    }
    catch(Exception& exc)
    {
        std::cerr << exc.displayText() << std::endl;
    }

Example 2

   try
        {
            // prepare session
            URI uri("https://www.google.com");
            HTTPClientSession session(uri.getHost(), uri.getPort());

            // prepare path
            string path(uri.getPathAndQuery());
            if (path.empty()) path = "/";

            // send request
            HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
            session.sendRequest(req);

            // get response
            HTTPResponse res;
            cout << res.getStatus() << " " << res.getReason() << endl;

            // print response
            istream &is = session.receiveResponse(res);
            StreamCopier::copyStream(is, cout);
        }
        catch (Exception &ex)
        {
            cerr << ex.displayText() << endl;
            return;
        }

The header files I included

#include "Poco/Net/HTTPClientSession.h"
#include "Poco/Net/HTTPRequest.h"
#include "Poco/Net/HTTPResponse.h"
#include "Poco/Net/HTTPCredentials.h"
#include "Poco/StreamCopier.h"
#include "Poco/NullStream.h"
#include "Poco/Path.h"
#include "Poco/URI.h"
#include "Poco/Exception.h"
#include <iostream>

using Poco::Net::HTTPClientSession;
using Poco::Net::HTTPRequest;
using Poco::Net::HTTPResponse;
using Poco::Net::HTTPMessage;
using Poco::StreamCopier;
using Poco::Path;
using Poco::URI;
using Poco::Exception;

using namespace std;

I am not sure what is wrong with the code. Is it because the url format is incorrect (don't think it has any problem though) or is it because it really didn't return any message at all? (but I tested it with postman and the 2 url did gave some kind of response. for example, it will return the html codes). Thank you.


Solution

  • Your problem is that you are using HTTPS URI. Your code works with modified HTTP URI: http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png

    If you want to use HTTPS, use code below, linked with PocoNetSSL library.

    #include <Poco/MD5Engine.h>
    #include <Poco/DigestStream.h>
    #include <Poco/Net/Context.h>
    #include <Poco/Net/HTTPSClientSession.h>
    
    void HttpsDownload() {
        try {
            Poco::URI uri("https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png");
            std::string path(uri.getPathAndQuery());
            if (path.empty())
                path = "/";
            const Poco::Net::Context::Ptr context = new Poco::Net::Context(
                    Poco::Net::Context::CLIENT_USE, "", "", "",
                    Poco::Net::Context::VERIFY_NONE, 9, false,
                    "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
            Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort(), context);
            Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1);
            Poco::Net::HTTPResponse response;
    
            bool isSuccess = false;
            session.sendRequest(request);
            std::istream &rs = session.receiveResponse(response);
            std::cout << response.getStatus() << " " << response.getReason() << std::endl;
            if (response.getStatus() != Poco::Net::HTTPResponse::HTTP_UNAUTHORIZED) {
                std::ofstream ofs("Poco_banner.png", std::fstream::binary);
                Poco::StreamCopier::copyStream(rs, ofs);
                isSuccess = true;
            } else {
                //it went wrong ?
                isSuccess = false;
            }
    
            if (!isSuccess) {
                std::cerr << "Invalid username or password" << std::endl;
                return;
            } else {
                std::cout << "done download" << std::endl;
            }
        } catch (Exception &exc) {
            std::cerr << exc.displayText() << std::endl;
        }
    }