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; Downloader::StreamData *streamBuffer = (Downloader::StreamData *)userdata;
size_t written = size * nmemb; size_t written = size * nmemb;
// Avoid pointer overflow // 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); memcpy(streamBuffer->buffer + streamBuffer->offset, ptr, written);
streamBuffer->offset += 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()); return prepareHeader(srcUrl);
curl_easy_setopt(curl, CURLOPT_HEADER, 1); }
curl_easy_setopt(curl, CURLOPT_NOBODY, 1); #endif
if (curl_easy_perform(curl) == CURLE_OK)
return true; 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 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; HeaderInfo info = prepareHeader(srcUrl);
CURL *header = curl_easy_init(); return info.contentSize;
if (prepareHeader(header, srcUrl)) }
{
curl_easy_getinfo(header, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength); void Downloader::getHeaderAsync(const std::string &srcUrl, const HeaderCallback &callback)
} {
curl_easy_cleanup(header); setHeaderCallback(callback);
#if(CC_TARGET_PLATFORM == CC_PLATFORM_WP8 || CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
return contentLength; 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/* = ""*/) 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(); CURL *header = curl_easy_init();
// Make a resume request // Make a resume request
curl_easy_setopt(header, CURLOPT_RESUME_FROM_LARGE, 0); 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; if (headerInfo.responseCode == HTTP_CODE_SUPPORT_RESUME)
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
{ {
_supportResuming = true; _supportResuming = true;
} }
@ -682,4 +727,4 @@ void Downloader::groupBatchDownload(const DownloadUnits &units)
clearBatchDownloadData(); clearBatchDownloadData();
} }
NS_CC_EXT_END NS_CC_EXT_END

View File

@ -60,7 +60,9 @@ public:
INVALID_URL, INVALID_URL,
INVALID_STORAGE_PATH INVALID_STORAGE_PATH,
PREPARE_HEADER_ERROR
}; };
struct Error struct Error
@ -99,11 +101,21 @@ public:
unsigned char *buffer; 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::unordered_map<std::string, DownloadUnit> DownloadUnits;
typedef std::function<void(const Downloader::Error &)> ErrorCallback; 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(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 std::string &, const std::string &)> SuccessCallback;
typedef std::function<void(const std::string &, const HeaderInfo &)> HeaderCallback;
int getConnectionTimeout(); int getConnectionTimeout();
@ -114,6 +126,8 @@ public:
void setProgressCallback(const ProgressCallback &callback) { _onProgress = callback; }; void setProgressCallback(const ProgressCallback &callback) { _onProgress = callback; };
void setSuccessCallback(const SuccessCallback &callback) { _onSuccess = callback; }; void setSuccessCallback(const SuccessCallback &callback) { _onSuccess = callback; };
void setHeaderCallback(const HeaderCallback &callback) { _onHeader = callback; };
ErrorCallback getErrorCallback() const { return _onError; }; ErrorCallback getErrorCallback() const { return _onError; };
@ -121,7 +135,11 @@ public:
SuccessCallback getSuccessCallback() const { return _onSuccess; }; 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 = ""); 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); 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); void downloadToBuffer(const std::string &srcUrl, const std::string &customId, const StreamData &buffer, const ProgressData &data);
@ -175,6 +196,8 @@ private:
ProgressCallback _onProgress; ProgressCallback _onProgress;
SuccessCallback _onSuccess; SuccessCallback _onSuccess;
HeaderCallback _onHeader;
std::string getFileNameFromUrl(const std::string &srcUrl); std::string getFileNameFromUrl(const std::string &srcUrl);
@ -193,4 +216,4 @@ int downloadProgressFunc(Downloader::ProgressData *ptr, double totalToDownload,
NS_CC_EXT_END NS_CC_EXT_END
#endif /* defined(__Downloader__) */ #endif /* defined(__Downloader__) */