cocos版本:3.6
阅读调试了下源码,并且自己做过实验了;
首先,我自己搭建的服务器是支持断点续传的,我用curl工具测试过,也按照cocos源码里的方式测试过。现在有个问题。
在cocos中,这段代码,开始会先用第一个需要下载的文件来检测服务器是否支持断点续传。
void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
{
// Make sure downloader won't be released
std::weak_ptr<Downloader> ptr = shared_from_this();
if (units.size() != 0)
{
// Test server download resuming support with the first unit
_supportResuming = false;
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))
{
long responseCode;
curl_easy_getinfo(header, CURLINFO_RESPONSE_CODE, &responseCode);
if (responseCode == HTTP_CODE_SUPPORT_RESUME)
{
_supportResuming = true;
}
}
curl_easy_cleanup(header);
int count = 0;
DownloadUnits group;
for (auto it = units.cbegin(); it != units.cend(); ++it, ++count)
{
if (count == FOPEN_MAX)
{
groupBatchDownload(group);
group.clear();
count = 0;
}
const std::string &key = it->first;
const DownloadUnit &unit = it->second;
group.emplace(key, unit);
}
if (group.size() > 0)
{
groupBatchDownload(group);
}
}
Director::getInstance()->getScheduler()->performFunctionInCocosThread([ptr, batchId]{
if (!ptr.expired()) {
std::shared_ptr<Downloader> downloader = ptr.lock();
auto callback = downloader->getSuccessCallback();
if (callback != nullptr)
{
callback("", "", batchId);
}
}
});
_supportResuming = false;
}
接着在
bool Downloader::prepareHeader(void *curl, const std::string &srcUrl) const
{
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;
else
return false;
}
我将curl_easy_perform执行结果打印了下发现是23;我对比了这个返回值表示写入错误。
我猜测,在开始下载之前,有先去下载version文件和project文件,也就是说在调用
void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
之前先是调用过了
void Downloader::download(const std::string &srcUrl, const std::string &customId, const FileDescriptor &fDesc, const ProgressData &data)
{
std::weak_ptr<Downloader> ptr = shared_from_this();
CURL *curl = curl_easy_init();
if (!curl)
{
this->notifyError(ErrorCode::CURL_EASY_ERROR, "Can not init curl with curl_easy_init", customId);
return;
}
// Download pacakge
curl_easy_setopt(curl, CURLOPT_URL, srcUrl.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, fileWriteFunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fDesc.fp);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, false);
curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, downloadProgressFunc);
curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, true);
if (_connectionTimeout) curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, _connectionTimeout);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_LIMIT, LOW_SPEED_LIMIT);
curl_easy_setopt(curl, CURLOPT_LOW_SPEED_TIME, LOW_SPEED_TIME);
CURLcode res = curl_easy_perform(curl);
if (res != CURLE_OK)
{
_fileUtils->removeFile(data.path + data.name + TEMP_EXT);
std::string msg = StringUtils::format("Unable to download file: [curl error]%s", curl_easy_strerror(res));
this->notifyError(msg, customId, res);
}
fclose(fDesc.fp);
curl_easy_cleanup(curl);
// This can only be done after fclose
if (res == CURLE_OK)
{
_fileUtils->renameFile(data.path, data.name + TEMP_EXT, data.name);
Director::getInstance()->getScheduler()->performFunctionInCocosThread([=]{
if (!ptr.expired())
{
std::shared_ptr<Downloader> downloader = ptr.lock();
auto successCB = downloader->getSuccessCallback();
if (successCB != nullptr)
{
successCB(data.url, data.path + data.name, data.customId);
}
}
});
}
}
这里设置了CURLOPT_WRITEFUNCTION以及CURLOPT_WRITEDATA;意思就是往CURLOPT_WRITEDATA指定的指针里写入,这里是文件指针,也就是下载目录下的version以及project文件;
我开始的想法以为是,在
void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
这里再次执行下载的时候,CURLOPT_WRITEDATA指向的指向的文件指针有问题;
所以我在这个函数里,CURLOPT_WRITEFUNCTION和CURLOPT_WRITEDATA我重新赋值了,而且写入函数我只是简单的返回接收的数据,并未做任何写入操作,可是奇怪的来了,curl_easy_perform的执行结果依然是23;
什么鬼;
我又把一切还原,又调试了一边,发现在执行
void Downloader::batchDownloadSync(const DownloadUnits &units, const std::string &batchId/* = ""*/)
的时候,连写入函数都断点不到~
无法,请大腿子们帮助!