2012-01-24 13 views
1

私は最近、完全に動作するWinInetプログラムをWinHTTPに移植しました。WinHTTPがnullバイトをダウンロードしていますか、結果バッファを正しくコピーしていませんか?

bool Get(Url url, std::vector<char>& data, ProgressCallbackFunction progressCallback = nullptr) throw() 
{ 
    long cl = -1; 
    DWORD clSize = sizeof(cl); 
    DWORD readCount = 0; 
    DWORD totalReadCount = 0; 
    DWORD availableBytes = 0; 
    std::vector<char> buf; 

    if (_session != NULL) 
     throw std::exception("Concurrent sessions are not supported"); 

    _session = ::WinHttpOpen(_userAgent.c_str(), WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, NULL); 
    auto connection = ::WinHttpConnect(_session, url.HostName.c_str(), url.Port, 0); 
    auto request = ::WinHttpOpenRequest(connection, TEXT("GET"), url.GetPathAndQuery().c_str(), NULL, NULL, NULL, WINHTTP_FLAG_REFRESH); 

    if (request == NULL) 
    { 
     _lastError = ::GetLastError(); 
     ::WinHttpCloseHandle(_session); 
     _session = NULL; 
     return false; 
    } 

    auto sendRequest = ::WinHttpSendRequest(request, WINHTTP_NO_ADDITIONAL_HEADERS, NULL, WINHTTP_NO_REQUEST_DATA, NULL, NULL, NULL); 
    if (sendRequest == FALSE) 
    { 
     _lastError = ::GetLastError(); 
     ::WinHttpCloseHandle(request); 
     ::WinHttpCloseHandle(_session); 
     _session = NULL; 
     return false; 
    } 

    if (::WinHttpReceiveResponse(request, NULL)) 
    { 
     if (progressCallback != nullptr && progressCallback != NULL) 
     { 
      if (!::WinHttpQueryHeaders(request, WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER, WINHTTP_HEADER_NAME_BY_INDEX, reinterpret_cast<LPVOID>(&cl), &clSize, 0)) 
      { 
       cl = -1;  
      } 
     } 

     while (::WinHttpQueryDataAvailable(request, &availableBytes)) 
     { 
      if (availableBytes) 
      { 
       buf.resize(availableBytes + 1); 
       auto hasRead = ::WinHttpReadData(request, &buf[0], availableBytes, &readCount); 
       totalReadCount += readCount; 
       data.insert(data.end(), buf.begin(), buf.begin() + readCount); 
       buf.clear(); 

       if (progressCallback != nullptr && progressCallback != NULL) 
       { 
        progressCallback(totalReadCount, cl, getProgress(totalReadCount, cl)); 
       } 
      } 
      else 
       break; 
     } 
    } 
    else 
    { 
     _lastError = ::GetLastError(); 
     ::WinHttpCloseHandle(request); 
     ::WinHttpCloseHandle(_session); 
     _session = NULL; 
     return false; 
    } 

    ::WinHttpCloseHandle(request); 
    ::WinHttpCloseHandle(_session); 
    _session = NULL; 
    return true; 
} 

コードは、それが要求されたURLをダウンロードすることでに動作します:ここで私はコードを一行にして全体をGETリクエストをラップするために書いた機能です。この問題は、サーバーがContent-Lengthヘッダーを返さないときに発生します(これはで、ほとんどの場合です)。コードは引き続きすべてのデータをダウンロードしますが、文字列に変換すると埋め込まれたnullバイトがあります。

上記のコードは、このように呼ばれる:

Url url(TEXT("http://msdn.microsoft.com/en-us/site/aa384376")); 
Client wc; 
std::vector<char> results; 
wc.Get(url, results); 
StdString html(results.begin(), results.end()); 
StdOut << html << endl; 

StdStringは<TCHAR>とのbasic_string ::のtypedef STDであり、STDOUTはUNICODEが定義されている場合に応じて、COUT又はwcoutを使用するマクロです。

nullが埋め込まれているため、すべての応答がコンソールに表示されるわけではありません。デバッグをオフにしてコードを実行したときに表示される出力can be viewed here(行の区切りは、単にテキストが自分のコンソールにラップされていることに注意してください)。最初のヌルは最後に "__in"の直後に表示され、 "Press any key to continue。..."という出力が表示されます。ここでは、出力のスクリーンキャップだ:

Console output

ここでヌルが閲覧可能な何の関係で表示される場所を正確に示すHTML変数の値のテキストビジュアライザ画面のキャップです:

Text visualizer for html

どこかに何か悪いコピーをしているのですか、私が気付いていないWinHTTPのニュアンスがありますか?

+0

動作を再現する例はありますか?私はあなたのコードをコピーし、そのmsdnページを試して、埋め込まれたnullがなかった。 – Luke

+0

次のリンクを含むように編集: http://pastebin.com/aEH9GzDE http://i.imgur.com/vRmNL.png http://i.imgur.com/eu8rH.png – jvstech

答えて

0

出力をさらに確認すると、ではなく、 nullsです。それらは、コンソールが間違って格納されているため(そして誤って変換されているため)表示できないユニコード文字です。私は

std::vector<unsigned char> 

std::vector<char> 

を変更することでGetメソッド(および呼び出し元のコード内)での問題を解決することができましたし、今、すべてが順調です。

関連する問題