2017-06-10 13 views
0

私はWinHTTPとWinInetを使用してHTTPクライアントを開発していましたが、最近はHTTP実装に最適なAPIを提供しているのでPOCOに切り替えることを考えました。POCO StreamCopierからHTTPSを経由してファイルのダウンロードを進める

私はうまくいきましたが、問題は、ストリームを定期的に照会するか、イベントの処理によってファイルのダウンロードの進行状況を知りたいということです。

これを行うことができるAPIの検索を開始した後、CountingOutputStreamを使用してファイルのアップロードシナリオの進捗状況を取得することについてこのHttp upload with progress info, in C++ (Poco/Boost)に触れました。私はそれが不完全で、私が期待した方法ではないと感じています。それは、そのCountingStreamの実際の実装をまったく使用しません。

私は、実装がCountingInputStreamによって可能であることを知りましたが、HttpStreamFactoryのオープンコールによって返されたストリームでそれを行う方法はわかりません。それを使用して複数のチャンクでストリームを読むことは可能ですか?私はUIに通知することができるように定期的にデータの量をクエリするか?

は、ここに私のコードです:

bool HttpClientConnection::DownloadFile (const std::string& file_url, const std::string file_location) 
{ 

     try 
     { 
       std::string complete_page_url = ""; 
       std::ofstream file_stream; 
       std::unique_ptr<std::istream> pStr  = nullptr; 


       if (isSecureConnection) 
       { 
        complete_page_url = "https://"; 
       } 
       else 
       { 
        complete_page_url = "http://"; 
       } 


       { 
        complete_page_url = serverHostName + file_url;// assuming the file url itself will contain leading forward slash 
       } 


      // Create the URI from the URL to the file. 
      URI uri(complete_page_url); 

       //std::auto_ptr<std::istream>pStr(URIStreamOpener::defaultOpener().open(uri); 
      //StreamCopier::copyStream(*pStr.get(), std::cout); 

      if (isSecureConnection) 
      { 
        std::unique_ptr<HTTPSStreamFactory> https_stream_factory = nullptr; 

        if (_buseProxy) 
        { 
         https_stream_factory = std::unique_ptr<HTTPSStreamFactory>(new HTTPSStreamFactory(proxyHostName, proxyPort, getProxyUserName(), getProxyPassword())); 
        } 
        else 
        { 
         https_stream_factory = std::unique_ptr<HTTPSStreamFactory>(new HTTPSStreamFactory()); 
        } 

        if (https_stream_factory) 
        { 
         pStr = std::unique_ptr<std::istream>(https_stream_factory->open(uri)); 
        } 
       } 
       else 
       { 
        std::unique_ptr<HTTPStreamFactory> http_stream_factory = nullptr; 

        if (_buseProxy) 
        { 
         http_stream_factory = std::unique_ptr<HTTPStreamFactory>(new HTTPStreamFactory(proxyHostName, proxyPort, getProxyUserName(), getProxyPassword())); 
        } 
        else 
        { 
         http_stream_factory = std::unique_ptr<HTTPStreamFactory>(new HTTPStreamFactory()); 
        } 

        if (http_stream_factory) 
        { 
         pStr = std::unique_ptr<std::istream>(http_stream_factory->open(uri)); 
        } 
      } 

      if (pStr) 
      { 
        file_stream.open(file_location, ios::out | ios::trunc | ios::binary); 

        StreamCopier::copyStream(*pStr.get(), file_stream); 

        file_stream.close(); 
      } 

      return true; 
} 
catch (Exception& exc) 
{ 
    if (httpLogger) 
    { 
             httpLogger->log(dcLogger::LOG_INFO, "HttpClient:: Exception in DownloadFile , error code: %d", exc.code()); 
    } 
} 

return false; 

} CountingOutputStreamにfileoutputストリームオブジェクト渡され、パラメータとしてカウント出力ストリームとタイマーを開始し

答えて

0

。タイマーは、データ送信が完了するまで定期的に呼び出され、書き込まれたバイト数を取得し、そのイベントを登録したユーザーに通知します。それはうまくいった!

shared_ptr<CountingOutputStream> cout_stream = shared_ptr<CountingOutputStream>(new CountingOutputStream(file_stream)); 

if (callback && callback_interval_in_millis > 0) 
{ 
    shared_ptr<FileProgressHandler> file_progress = shared_ptr<FileProgressHandler>(new FileProgressHandler(cout_stream, file_size, callback)); 

    if (file_progress) 
    { 
     TimerCallback<FileProgressHandler> callback(*(file_progress.get()), &FileProgressHandler::onTimer); 

     timer = shared_ptr<Timer>(new Timer(0, callback_interval_in_millis)); 

     if (timer) 
     { 
      timer->start(callback); 
     } 
    } 

    StreamCopier::copyStream(*pStr.get(), *cout_stream); 

    if (timer) 
    { 
     timer->stop(); 
    } 
} 

void onTimer(Timer& timer) 
{ 
    try 
    { 
     if (progress_callback) 
     { 
      int data_processed = 0; 

      counting_io_stream ? data_processed = counting_io_stream->chars() : __noop; 

      if (data_processed != total_processed_data) 
      { 
       total_processed_data = data_processed; 

       int percent  = (100 * total_processed_data)/file_size; 

       progress_callback(percent); 
      } 
     } 
    } 
    catch(const std::bad_function_call& e) 
    { 

    } 
    catch(const std::bad_weak_ptr& e) 
    { 

    } 
    catch(const std::exception& e) 
    { 

    } 
} 
関連する問題