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的修改、
