diff --git a/include/wx/private/webrequest.h b/include/wx/private/webrequest.h index 0812304fac..497bbfc170 100644 --- a/include/wx/private/webrequest.h +++ b/include/wx/private/webrequest.h @@ -187,6 +187,10 @@ protected: void ReportDataReceived(size_t sizeReceived); + // This function can optionally be called to preallocate the read buffer, + // if the total amount of data to be downloaded is known in advance. + void PreAllocBuffer(size_t sizeNeeded); + private: // Called by wxWebRequestImpl only. friend class wxWebRequestImpl; diff --git a/include/wx/private/webrequest_curl.h b/include/wx/private/webrequest_curl.h index d0e2f8a5d7..25b90a80ba 100644 --- a/include/wx/private/webrequest_curl.h +++ b/include/wx/private/webrequest_curl.h @@ -114,11 +114,12 @@ public: // Methods called from libcurl callbacks size_t CURLOnWrite(void *buffer, size_t size); size_t CURLOnHeader(const char* buffer, size_t size); - int CURLOnProgress(); + int CURLOnProgress(curl_off_t); private: wxWebRequestHeaderMap m_headers; wxString m_statusText; + wxFileOffset m_knownDownloadSize; CURL* GetHandle() const { return static_cast(m_request).GetHandle(); } diff --git a/src/common/webrequest.cpp b/src/common/webrequest.cpp index 351a4b76ae..70dbf7232b 100644 --- a/src/common/webrequest.cpp +++ b/src/common/webrequest.cpp @@ -688,6 +688,11 @@ void* wxWebResponseImpl::GetDataBuffer(size_t sizeNeeded) return m_readBuffer.GetAppendBuf(sizeNeeded); } +void wxWebResponseImpl::PreAllocBuffer(size_t sizeNeeded) +{ + m_readBuffer.SetBufSize(sizeNeeded); +} + void wxWebResponseImpl::ReportDataReceived(size_t sizeReceived) { m_readBuffer.UngetAppendBuf(sizeReceived); diff --git a/src/common/webrequest_curl.cpp b/src/common/webrequest_curl.cpp index d247e844af..f8d2aac47d 100644 --- a/src/common/webrequest_curl.cpp +++ b/src/common/webrequest_curl.cpp @@ -67,7 +67,7 @@ static size_t wxCURLHeader(char *buffer, size_t size, size_t nitems, void *userd return static_cast(userdata)->CURLOnHeader(buffer, size * nitems); } -int wxCURLXferInfo(void* clientp, curl_off_t WXUNUSED(dltotal), +int wxCURLXferInfo(void* clientp, curl_off_t dltotal, curl_off_t WXUNUSED(dlnow), curl_off_t WXUNUSED(ultotal), curl_off_t WXUNUSED(ulnow)) @@ -75,7 +75,7 @@ int wxCURLXferInfo(void* clientp, curl_off_t WXUNUSED(dltotal), wxCHECK_MSG( clientp, 0, "invalid curl progress callback data" ); wxWebResponseCURL* response = reinterpret_cast(clientp); - return response->CURLOnProgress(); + return response->CURLOnProgress(dltotal); } int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal, @@ -90,6 +90,8 @@ int wxCURLProgress(void* clientp, double dltotal, double dlnow, double ultotal, wxWebResponseCURL::wxWebResponseCURL(wxWebRequestCURL& request) : wxWebResponseImpl(request) { + m_knownDownloadSize = 0; + curl_easy_setopt(GetHandle(), CURLOPT_WRITEDATA, static_cast(this)); curl_easy_setopt(GetHandle(), CURLOPT_HEADERDATA, static_cast(this)); @@ -152,8 +154,17 @@ size_t wxWebResponseCURL::CURLOnHeader(const char * buffer, size_t size) return size; } -int wxWebResponseCURL::CURLOnProgress() +int wxWebResponseCURL::CURLOnProgress(curl_off_t total) { + if ( m_knownDownloadSize != total ) + { + if ( m_request.GetStorage() == wxWebRequest::Storage_Memory ) + { + PreAllocBuffer(static_cast(total)); + } + m_knownDownloadSize = total; + } + return 0; }