Add get header and callback for Downloader

This commit is contained in:
pandamicro 2015-04-23 19:07:07 +08:00
parent 51f949540c
commit ec41965add
2 changed files with 95 additions and 27 deletions

View File

@ -52,7 +52,7 @@ size_t bufferWriteFunc(void *ptr, size_t size, size_t nmemb, void *userdata)
Downloader::StreamData *streamBuffer = (Downloader::StreamData *)userdata;
size_t written = size * nmemb;
// Avoid pointer overflow
if (streamBuffer->offset + written <= static_cast<size_t>(streamBuffer->total))
if (streamBuffer->offset + written <= static_cast<size_t>(streamBuffer->total))
{
memcpy(streamBuffer->buffer + streamBuffer->offset, ptr, written);
streamBuffer->offset += written;
@ -273,28 +273,74 @@ void Downloader::prepareDownload(const std::string &srcUrl, const std::string &s
}
}
bool Downloader::prepareHeader(void *curl, const std::string &srcUrl) const
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
Downloader::HeaderInfo Downloader::prepare(const std::string &srcUrl)
{
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
curl_easy_setopt(curl, CURLOPT_HEADER, 1);
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
if (curl_easy_perform(curl) == CURLE_OK)
return true;
return prepareHeader(srcUrl);
}
#endif
Downloader::HeaderInfo Downloader::prepareHeader(const std::string &srcUrl, void* header/* = nullptr */)
{
bool headerGiven = true;
HeaderInfo info;
info.valid = false;
if (!header)
{
headerGiven = false;
header = curl_easy_init();
}
curl_easy_setopt(header, CURLOPT_URL, srcUrl.c_str());
curl_easy_setopt(header, CURLOPT_HEADER, 1);
curl_easy_setopt(header, CURLOPT_NOBODY, 1);
if (curl_easy_perform(header) == CURLE_OK)
{
char *url;
char *contentType;
curl_easy_getinfo(header, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(header, CURLINFO_CONTENT_TYPE, &contentType);
curl_easy_getinfo(header, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &info.contentSize);
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &info.responseCode);
info.url = url;
info.contentType = contentType;
info.valid = true;
if (_onHeader)
{
_onHeader(srcUrl, info);
}
}
else
return false;
{
info.contentSize = -1;
std::string msg = StringUtils::format("Can not get content size of file (%s) : Request header failed", srcUrl.c_str());
this->notifyError(ErrorCode::PREPARE_HEADER_ERROR, msg);
}
if (!headerGiven) {
curl_easy_cleanup(header);
}
return info;
}
long Downloader::getContentSize(const std::string &srcUrl) const
long Downloader::getContentSize(const std::string &srcUrl)
{
double contentLength = -1;
CURL *header = curl_easy_init();
if (prepareHeader(header, srcUrl))
{
curl_easy_getinfo(header, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
}
curl_easy_cleanup(header);
return contentLength;
HeaderInfo info = prepareHeader(srcUrl);
return info.contentSize;
}
void Downloader::getHeaderAsync(const std::string &srcUrl, const HeaderCallback &callback)
{
setHeaderCallback(callback);
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
auto t = std::thread(&Downloader::prepare, this, srcUrl);
#else
auto t = std::thread(&Downloader::prepareHeader, this, srcUrl, nullptr);
#endif
t.detach();
}
void Downloader::downloadToBufferAsync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId/* = ""*/)
@ -482,11 +528,10 @@ void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string
CURL *header = curl_easy_init();
// Make a resume request
curl_easy_setopt(header, CURLOPT_RESUME_FROM_LARGE, 0);
if (prepareHeader(header, units.begin()->second.srcUrl))
HeaderInfo headerInfo = prepareHeader(units.begin()->second.srcUrl, header);
if (headerInfo.valid)
{
long responseCode;
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
if (headerInfo.responseCode == HTTP_CODE_SUPPORT_RESUME)
{
_supportResuming = true;
}
@ -682,4 +727,4 @@ void Downloader::groupBatchDownload(const DownloadUnits &units)
clearBatchDownloadData();
}
NS_CC_EXT_END
NS_CC_EXT_END

View File

@ -60,7 +60,9 @@ public:
INVALID_URL,
INVALID_STORAGE_PATH
INVALID_STORAGE_PATH,
PREPARE_HEADER_ERROR
};
struct Error
@ -99,11 +101,21 @@ public:
unsigned char *buffer;
};
struct HeaderInfo
{
bool valid;
std::string url;
std::string contentType;
double contentSize;
double responseCode;
};
typedef std::unordered_map<std::string, DownloadUnit> DownloadUnits;
typedef std::function<void(const Downloader::Error &)> ErrorCallback;
typedef std::function<void(double, double, const std::string &, const std::string &)> ProgressCallback;
typedef std::function<void(const std::string &, const std::string &, const std::string &)> SuccessCallback;
typedef std::function<void(const std::string &, const HeaderInfo &)> HeaderCallback;
int getConnectionTimeout();
@ -114,6 +126,8 @@ public:
void setProgressCallback(const ProgressCallback &callback) { _onProgress = callback; };
void setSuccessCallback(const SuccessCallback &callback) { _onSuccess = callback; };
void setHeaderCallback(const HeaderCallback &callback) { _onHeader = callback; };
ErrorCallback getErrorCallback() const { return _onError; };
@ -121,7 +135,11 @@ public:
SuccessCallback getSuccessCallback() const { return _onSuccess; };
long getContentSize(const std::string &srcUrl) const;
HeaderCallback getHeaderCallback() const { return _onHeader; };
long getContentSize(const std::string &srcUrl);
void getHeaderAsync(const std::string &srcUrl, const HeaderCallback &callback);
void downloadToBufferAsync(const std::string &srcUrl, unsigned char *buffer, const long &size, const std::string &customId = "");
@ -152,7 +170,10 @@ protected:
void prepareDownload(const std::string &srcUrl, const std::string &storagePath, const std::string &customId, bool resumeDownload, FileDescriptor *fDesc, ProgressData *pData);
bool prepareHeader(void *curl, const std::string &srcUrl) const;
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
HeaderInfo prepare(const std::string &srcUrl);
#endif
HeaderInfo prepareHeader(const std::string &srcUrl, void* header = nullptr);
void downloadToBuffer(const std::string &srcUrl, const std::string &customId, const StreamData &buffer, const ProgressData &data);
@ -175,6 +196,8 @@ private:
ProgressCallback _onProgress;
SuccessCallback _onSuccess;
HeaderCallback _onHeader;
std::string getFileNameFromUrl(const std::string &srcUrl);
@ -193,4 +216,4 @@ int downloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload,
NS_CC_EXT_END
#endif /* defined(__Downloader__) */
#endif /* defined(__Downloader__) */