1、Cocos2dx热更新因为文件名含有空格,ios下载失败bug修改
问题描述:
项目中偶尔遇到美术图片命名时不规范,导致图片名字含有空格。导致ios热更新时,遇到下载失败。
解决方案:
1.从新改名字(以后命名一定要规范)
2.空格转义 解决下载失败问题
url
web 开发中通过问号(?)方式在浏览器地址栏中传值时。浏览器是通过“&”来区分问号后的参数个数的。 如果出现传值参数中带有“&”时,在接受页面就会出现错误,类似如下请求路径:/next.jsp?param1=hendhs89&furej & param2=sss
参数param1中含有转义字符“&” ,这样会导致被请求页的参数接收错误。
在传值前 通过 java.net.URLEncoder.encode(param1) 编码处理后,可将转义字符转为16进制;
1. + URL 中+号表示空格 %2B
2. 空格 URL中的空格可以用+号或者编码 %20
3. / 分隔目录和子目录 %2F
4. ? 分隔实际的 URL 和参数 %3F
5. % 指定特殊字符 %25
6. # 表示书签 %23
7. & URL中指定的参数间的分隔符%26
8. = URL中指定参数的值 %3D
9. ! URL中指定参数的值 %2
具体解决方案
1、AssetsManagerEx::startUpdate()中,拼接地址时,将空格转义
void AssetsManagerEx::startUpdate() { if (_updateState != State::NEED_UPDATE) return; _updateState = State::UPDATING; // Clean up before update _failedUnits.clear(); _downloadUnits.clear(); _compressedFiles.clear(); _totalWaitToDownload = _totalToDownload = 0; _percent = _percentByFile = _sizeCollected = _totalSize = 0; _downloadedSize.clear(); _totalEnabled = false; // Temporary manifest exists, resuming previous download if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest)) { _tempManifest->genResumeAssetsList(&_downloadUnits); _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size(); this->batchDownload(); std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload); dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); } // Check difference else { // Temporary manifest not exists or out of date, // it will be used to register the download states of each asset, // in this case, it equals remote manifest. _tempManifest->release(); _tempManifest = _remoteManifest; std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest); if (diff_map.size() == 0) { updateSucceed(); } else { // Generate download units for all assets that need to be updated or added std::string packageUrl = _remoteManifest->getPackageUrl(); for (auto it = diff_map.begin(); it != diff_map.end(); ++it) { Manifest::AssetDiff diff = it->second; if (diff.type == Manifest::DiffType::DELETED) { _fileUtils->removeFile(_storagePath + diff.asset.path); } else { std::string path = diff.asset.path; // Create path _fileUtils->createDirectory(basename(_storagePath + path)); DownloadUnit unit; unit.customId = it->first; std::string str(path),s2(" "),s3("%20"); std::string::size_type pos=0; std::string::size_type a=s2.size(); std::string::size_type b=s3.size(); while((pos=str.find(s2,pos))!=std::string::npos) { str.replace(pos,a,s3); pos+=b; } unit.srcUrl = packageUrl + str; unit.storagePath = _storagePath + path; _downloadUnits.emplace(unit.customId, unit); } } // Set other assets' downloadState to SUCCESSED auto &assets = _remoteManifest->getAssets(); for (auto it = assets.cbegin(); it != assets.cend(); ++it) { const std::string &key = it->first; auto diffIt = diff_map.find(key); if (diffIt == diff_map.end()) { _tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED); } } _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size(); this->batchDownload(); std::string msg = StringUtils::format("Start to update %d files from remote package.", _totalToDownload); dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); } } }
2、Manifest.cpp
void Manifest::genResumeAssetsList(DownloadUnits *units) const { for (auto it = _assets.begin(); it != _assets.end(); ++it) { Asset asset = it->second; if (asset.downloadState != DownloadState::SUCCESSED) { DownloadUnit unit; unit.customId = it->first; std::string str(asset.path),s2(" "),s3("%20"); std::string::size_type pos=0; std::string::size_type a=s2.size(); std::string::size_type b=s3.size(); while((pos=str.find(s2,pos))!=std::string::npos) { str.replace(pos,a,s3); pos+=b; } unit.srcUrl = _packageUrl + str; unit.storagePath = _manifestRoot + asset.path; units->emplace(unit.customId, unit); } } }
2、Cocos2dx热更新因为文件名含有空格,ios下载失败bug修改
问题描述:
AsstsManagerEx: project.manifest may be downloaded twice。
project.manifest下载两次 ,导致热更新失败。打印log提示 解析project.manifest失败。
解决方案:
Cocos 3.14版本 自己解决了这个问题,根据就该日志 更新下载器。
3、更新过程强制退出,导致不能缓存下载。下载失败之后,不对比MD5所有文件都下载bug。
新版本不知道有没有。这个对应版本是 3.11
解决思路 。
下载器一开始先判断有没有缓存文件,有缓存文件的话,直接读取缓存文件。由于上一次强退没有及时将下载进度写到缓存文件中
所以所有文件的状态都是1.这里由于是临时清单文件,没有做MD5对比。所有所有文件都被添加到下载清单,出现bug
如果正常出错,没有强退。下载器会正常调用,写临时清单,这个不会有bug。
void AssetsManagerEx::startUpdate() { if (_updateState != State::NEED_UPDATE) return; _updateState = State::UPDATING; // Clean up before update _failedUnits.clear(); _downloadUnits.clear(); _compressedFiles.clear(); _totalWaitToDownload = _totalToDownload = 0; _percent = _percentByFile = _sizeCollected = _totalSize = 0; _downloadedSize.clear(); _totalEnabled = false; // Temporary manifest exists, resuming previous download if (_tempManifest->isLoaded() && _tempManifest->versionEquals(_remoteManifest)) { std::unordered_map<std::string, Manifest::AssetDiff> diff_map = _localManifest->genDiff(_remoteManifest); if (diff_map.size() == 0) { updateSucceed(); } else { // Set other assets' downloadState to SUCCESSED auto &assets = _remoteManifest->getAssets(); for (auto it = assets.cbegin(); it != assets.cend(); ++it) { const std::string &key = it->first; auto diffIt = diff_map.find(key); if (diffIt == diff_map.end()) { _tempManifest->setAssetDownloadState(key, Manifest::DownloadState::SUCCESSED); } } _tempManifest->genResumeAssetsList(&_downloadUnits); _totalWaitToDownload = _totalToDownload = (int)_downloadUnits.size(); this->batchDownload(); std::string msg = StringUtils::format("Resuming from previous unfinished update, %d files remains to be finished.", _totalToDownload); dispatchUpdateEvent(EventAssetsManagerEx::EventCode::UPDATE_PROGRESSION, "", msg); } } // Check difference else
附
遇到问题不要着急,一步一步确定问题。经常看官网的coco动态,新版本的发布,以及bug的修改、