1. 程式人生 > >ionic 專案檔案下載總結

ionic 專案檔案下載總結

一、前景

最近專案中使用了檔案下載,避免再次掉坑於是寫篇總結!

二、外掛簡介

cordova專案的檔案下載一般會使用到cordova-plugin-file、cordova-plugin-file-transfer、cordova-plugin-file-opener2三個外掛。

cordova plugin add cordova-plugin-file
cordova plugin add cordova-plugin-file-transfer
cordova plugin add https://github.com/pwlin/cordova-plugin-file
-opener2.git

三、初始化不同平臺下載目錄

// 下載目錄
var downloadPath;

/**
 * 初始化app的下載目錄
 */
initDownloadDirectory: function () {
  var deferred = $q.defer();

  /**
   * cordova.file.dataDirectory 不同平臺對應位置如下
   *  android:'data/data/<app-id>/files/'
   *  IOS:'/var/mobile/Applications/<UUID>/Library/NoCloud/'
   */
/** * 因android平臺,apk型別的檔案放到cordova.file.dataDirectory下,將無法正常安裝 */ if (ionic.Platform.isAndroid()) { // 初始化android平臺的下載目錄 downloadPath = cordova.file.externalRootDirectory + SystemConstant('download_path') + "/"; this.createDir(cordova.file.externalRootDirectory, SystemConstant('download_path'
)) .then(function (success) { downloadPath = success.nativeURL; deferred.resolve(success); }, function (error) { console.log("[download] init android platform's download dir occurred error :" + angular.toJson(error)); deferred.reject(error); }); } else { // 初始化IOS平臺的下載目錄 downloadPath = cordova.file.documentsDirectory + SystemConstant('download_path') + "/"; this.createDir(cordova.file.documentsDirectory, SystemConstant('download_path')) .then(function (success) { downloadPath = success.nativeURL; console.log(success.nativeURL); deferred.resolve(success); }, function (error) { console.log("[download] init IOS platform's download dir occurred error :" + angular.toJson(error)); deferred.reject(error); }); } } /** * 建立目錄 * @param path 目錄 * @param directory 目錄名稱 */ createDir: function (path, directory) { var deferred = $q.defer(); $cordovaFile.createDir(path, directory, false) .then(function (success) { deferred.resolve(success); }, function (error) { console.log("[download] create dir occurred error :" + angular.toJson(error)); deferred.reject(error); }); return deferred.promise; }

四、Android和IOS檔案系統對比

這裡寫圖片描述
這裡寫圖片描述

五、檔案下載

坑一:直接從伺服器返回的檔案流下載沒問題,但是,如果伺服器返回的為FTP的檔案流就存在下載後的檔案全是亂碼
解決:

headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'accept-encoding': 'gzip,deflate,sdch',
    'accept-language': 'zh-CN,zh;q=0.8,en;q=0.6'
  };

坑二: 同一檔案Android平臺可以下載,IOS平臺報錯(原因:檔名稱存在中文)

{
    "code":1,
    "target":null,
    "http_status":201,
    "body":"Could not create target file"
}

解決:

 if (ionic.Platform.isIOS()) {
    fileName = encodeURI(fileName);
}

下載完整程式碼如下:

/**
 * 檔案下載
 * @param url 資源定位
 * @param targetPath 檔案儲存位置
 * @param fileName 檔名稱
 * @param isOpen 下載完成後是否開啟
 * @returns {Promise}
 */
download: function (url, targetPath, fileName, isOpen) {
  var deferred = $q.defer();

  var trustAllHosts = true;
  // 選項
  var options = {};
  //新增headers資訊
  var headers = {
    'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'accept-encoding': 'gzip,deflate,sdch',
    'accept-language': 'zh-CN,zh;q=0.8,en;q=0.6'
  };
  options.headers = headers;

  $ionicLoading.show({template: "已經下載0%"});
  $cordovaFileTransfer.download(url, targetPath, options, trustAllHosts)
    .then(function (success) {
      $ionicLoading.hide();

      if (isOpen) {
        // 檔案型別
        var fileType = fileName.substring(fileName.lastIndexOf('.') + 1, fileName.length);

        //開啟下載檔案
        $cordovaFileOpener2.open(targetPath, MIME_MapTable(fileType))
          .then(function (success) {
            deferred.resolve(success);
          }, function (error) {
            console.log("[download] open file occurred error :" + angular.toJson(error));
            deferred.reject({message: FileConstant('FILE_OPEN_FAIL')});
          });
      } else {
        deferred.resolve(success);
      }
    }, function (error) {
      $ionicLoading.hide();
      console.log("[download] download file occurred error :" + angular.toJson(error));

      deferred.reject({message: FileConstant('DOWNLOAD_FAIL')});
    }, function (progress) {
      $timeout(function () {
        var downloadProgress = (progress.loaded / progress.total) * 100;
        $ionicLoading.show({template: "已經下載" + Math.floor(downloadProgress) + "%"});

        if (downloadProgress > 99) {
          $ionicLoading.hide();
        }
      });
    });

  return deferred.promise;
}

/**
 * 附件下載
 * @param url 資源定位
 * @param fileName 檔名
 * @returns {Promise}
 */
downloadAttachment: function (url, fileName) {
  var deferred = $q.defer();

  url = encodeURI(url);
  // 儲存路徑
  var targetPath = downloadPath;

  // IOS 平臺,如果檔名稱存在中文時需要轉碼
  if (ionic.Platform.isIOS()) {
    targetPath += encodeURI(fileName);
  } else {
    targetPath += fileName;
  }

  this.download(url, targetPath, fileName, true)
    .then(function (success) {
      deferred.resolve(success);
    }, function (error) {
      deferred.reject(error);
    });

  return deferred.promise;
}

/**
 * MIME 資源型別
 */
.constant('MIME_MapTable', function (key) {
  return {
    "3gp": "video/3gpp",
    "apk": "application/vnd.android.package-archive",
    "asf": "video/x-ms-asf",
    "avi": "video/x-msvideo",
    "bin": "application/octet-stream",
    "bmp": "image/bmp",
    "c": "text/plain",
    "class": "application/octet-stream",
    "conf": "text/plain",
    "cpp": "text/plain",
    "exe": "application/octet-stream",
    "gif": "image/gif",
    "gtar": "application/x-gtar",
    "gz": "application/x-gzip",
    "h": "text/plain",
    "htm": "text/html",
    "html": "text/html",
    "jar": "application/java-archive",
    "java": "text/plain",
    "jpeg": "image/jpeg",
    "jpg": "image/jpeg",
    "js": "application/x-javascript",
    "log": "text/plain",
    "m3u": "audio/x-mpegurl",
    "m4a": "audio/mp4a-latm",
    "m4b": "audio/mp4a-latm",
    "m4p": "audio/mp4a-latm",
    "m4u": "video/vnd.mpegurl",
    "m4v": "video/x-m4v",
    "mov": "video/quicktime",
    "mp2": "audio/x-mpeg",
    "mp3": "audio/x-mpeg",
    "mp4": "video/mp4",
    "mpc": "application/vnd.mpohun.certificate",
    "mpe": "video/mpeg",
    "mpeg": "video/mpeg",
    "mpg": "video/mpeg",
    "mpg4": "video/mp4",
    "mpga": "audio/mpeg",
    "msg": "application/vnd.ms-outlook",
    "ogg": "audio/ogg",
    "pdf": "application/pdf",
    "png": "image/png",
    "pps": "application/vnd.ms-powerpoint",
    "prop": "text/plain",
    "rar": "application/x-rar-compressed",
    "rc": "text/plain",
    "rmvb": "audio/x-pn-realaudio",
    "rtf": "application/rtf",
    "sh": "text/plain",
    "tar": "application/x-tar",
    "tgz": "application/x-compressed",
    "txt": "text/plain",
    "wav": "audio/x-wav",
    "wma": "audio/x-ms-wma",
    "wmv": "audio/x-ms-wmv",
    "wps": "application/vnd.ms-works",
    "xml": "text/plain",
    "xls": "application/vnd.ms-excel",
    "xlsx": "application/vnd.ms-excel",
    "doc": "application/msword",
    "docx": "application/msword",
    "ppt": "application/vnd.ms-powerpoint",
    "pptx": "application/vnd.ms-powerpoint",
    "z": "application/x-compress",
    "zip": "application/zip"
  }[key];
})