App开发过程中,涉及到文件系统操作这一块,比如应用内更新, 服务器资源下载,资源上传操作,今天新版本发布,有用户碰到华为手机更新解析错误的问题,在研究的同时,总结一下这方面的知识。
解析错误原因
解析错误的原因可能有如下两种:
- 签名不对应
- 安装包不完整
在排除掉签名问题之后,考虑到安装包的完整性问题,通过查看手机文件管理系统发现,apk安装包每下载一次就越来越大,有可能是用户第一次下载中断,导致有不完整apk在存储中,下次继续更新的时候,采用的是追加写
的方式,因此越来越大,同时业务无法在得到完整的apk包了,因此一直更新不成功。
那么为什么会追加写
呢,考虑到近期添加的用来实现断点续传的插件cordova-plugin-pause-resume-download
,会不会是他导致的呢?经过几次测试之后,排出了他的原因?因为我重新rm、add平台之后,问题突然不存在了。
解析错误解决
- 问题很奇怪,为什么版本更新有时候会采取
追加写
的方式呢?这里暂时没有思考清楚。 - download API有没有配置参数可以设置是
追加写
还是覆盖写
呢?暂时没查到。 - 目前解决方案:判断文件是否存在,存在删除文件再下载,不存在直接下载。代码如下:
window.resolveLocalFileSystemURL(cordova.file.externalApplicationStorageDirectory, function (fileEntry) { fileEntry.getDirectory("Download", {create: true, exclusive: false}, function (fileEntry) { var filname="xxx.apk"; //下载路径 var targetPath = fileEntry.toInternalURL() + filname; //APP下载存放的路径,可以使用cordova file插件进行相关配置 $cordovaFile.checkFile(fileEntry.toInternalURL(),filname).then(function (success) { $cordovaFile.removeFile(fileEntry.toInternalURL(),filname).then(function(success){ startDownLoad(downloadUrl,targetPath,options,trustHosts); },function(error){ myNote.myNotice("下载失败"); }); },function (error) { startDownLoad(downloadUrl,targetPath,options,trustHosts); }); }); }); function startDownLoad(downloadUrl,targetPath,options,trustHosts){ $cordovaFileTransfer.download(downloadUrl, targetPath, options, trustHosts).then(function (result) { //下载成功,打开安装 console.log(targetPath); cordova.plugins.fileOpener2.open(targetPath, 'application/vnd.android.package-archive', { error: function (e) { console.log('Error status: ' + e.status + ' - Error message: ' + e.message); }, success: function () { console.log('file opened successfully'); } }); $ionicLoading.hide(); }, function (error) { //下载失败友好提示 myNote.myNotice("下载失败"); }, function (progress) { //进度,这里使用文字显示下载百分比 $timeout(function () { if (progress.lengthComputable) { var downloadProgress = (progress.loaded / progress.total) * 100; $ionicLoading.show({ template: "已经下载:" + Math.floor(downloadProgress) + "%" }); if (downloadProgress == 100) { $ionicLoading.hide(); } } }, 18); }); }
Cordova文件操作
Cordova提供了file插件,通过这个插件可以让我们访问手机上的大部分文件和文件夹,包括应用内部文件、SD卡上的文件等等,该插件是与HTML5的文件操作方法结合在一起的。
resolveLocalFileSystemURL VS requestFileSystem
在使用文件操作api时,我们需要一个FileSystem对象,可以通过上述方法得到,那么两者之间的区别呢?阅读源码发现两者大致一样,当你访问的未知位于cordova.file.*下时(绝大多数情况都是访问它),建议使用resolveLocalFileSystemURL,如果需要访问文件系统的根,使用requestFileSystem方法。
关键的函数是resolveLocalFileSystemURL,有了这个方法,我们才可以访问外部文件和文件夹,因为这会把一个PATH转变成entry,而entry是操作文件和文件夹的关键
。读取文件
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory,function(root){ root.getFile('demo.txt', {create:false}, function(fileEntry) { fileEntry.file(function(file) { var reader = new FileReader(); reader.onloadend = function(e) { alert(this.result); }; reader.readAsText(file); }, function(err){console.log('读取出错');}); }, function(err){console.log('找不到文件');}); },function(err){});
- 创建文件
root.getFile('demo.txt', {true}, function(fileEntry) { //成功代码 },function(err){ //错误代码 });
- 创建文件夹
root.getDirectory('my_folder', {create: true}, function(dirEntry) { alert('您创建了:' + dirEntry.name + ' 文件夹。'); }, function(err){ console.log('创建文件夹出错'); });
- 检查文件或文件夹是否存在
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory+'demo/',function(root){ console.log('文件夹存在'); },function(err){ console.log('文件夹不存'); });
- 删除文件
window.resolveLocalFileSystemURL(cordova.file.externalRootDirectory+'demo/',function(root){ root.getFile('demo.txt',{create:false},function(fentry){ fentry.remove(function() { console.log('删除成功'); },function(err){ console.log('删除失败') }); },function(err){console.log('删除文件出错');}); },function(err){ console.log('文件夹不存'); });
ngCordova文件操作
对常用插件进行了封装,但是并不代表他不依赖插件,插件还是需要安装的,他只是进一步封装了插件的API。
使用如下:
- 入口注入ngCordova
使用到对应插件时,注入service,通常以
$
打头,比如接下来要介绍的三个文件类插件的服务名称如下- $cordovaFile
- $cordovaFileOpener2
- $cordovaFileTransfer
cordova-plugin-file文件管理
- 获取剩余空间
- 检查文件夹或文件是否存在
- 创建文件夹或文件
- 删除文件夹或文件
- 写文件
- 读文件
- 移动文件夹或文件
- 复制文件夹或文件
- API:$cordovaFile
cordova-plugin-file-opener2文件打开
- 打开文件
- 卸载应用
- 检查某软件是否安装
- API:$cordovaFileOpener2
cordova-plugin-file-transfer文件传输
- 上传
- 下载
- API:$cordovaFileTransfer