Better

Ethan的博客,欢迎访问交流

Cordova的文件系统编程

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文件打开

  • cordova-plugin-file-transfer文件传输



留言