AssetsManagerEx断点续传问题

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/* = ""*/)

的时候,连写入函数都断点不到~
无法,请大腿子们帮助!

@panda

麻烦看下嘛,谢谢了

@panda

麻烦看下嘛,谢谢了,怕at不到~~~,sor

服务器地址和资源路径都在图中,可以试下

@minggo

麻烦看下呢

遇到同样的问题,求解决
@minggo

@王哲
老哥,我该找谁

我也不知道应该找谁

你返回的也是23?

对的,返回23

问题解决了;
办法就是别用cocos2dx;
没bug?tan90
论坛发帖有人回?tan90
官方在意?tan90
去年买了个表

升级到3.12版本,用新版的AssetsManagerEx就可以了