/** * 参考的API: * http://w3c.github.io/quota-api/ * */ //文件系统请求标识 window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem //根据URL取得文件的读取权限 window.resolveLocalFileSystemURL = window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL //临时储存和永久存储 navigator.temporaryStorage = navigator.temporaryStorage || navigator.webkitTemporaryStorage; navigator.persistentStorage = navigator.persistentStorage || navigator.webkitPersistentStorage; //常量 const _TEMPORARY = 'temporary', _PERSISTENT = 'persistent' /** * 转为promise,主要是把 a.b(param1,param2,successCallback,errorCall) 转为promise * @param {*期待的是函数} obj * @param {*上下文} ctx * @param {*参数} args */ function toPromise(obj, ctx, ...args) { if (!obj) return obj //如果已经是Promise对象 if ('function' == typeof obj.then) return obj //若obj是函数直接转换 if ('function' == typeof obj) return _toPromise(obj) return obj; //函数转成 promise function _toPromise(fn) { return new Promise(function (resolve, reject) { fn.call(ctx, ...args, (...ags) => { //多个参数返回数组,单个直接返回对象 resolve(ags && ags.length > 1 ? ags : ags[0]) }, (err) => { reject(err) }) }) } } /** * 查询和申请定额 * 测试脚本: * 使用情况: FileStorageQuota.instance.queryInfo().then(data=>console.log(data)) * 申请空间: FileStorageQuota.instance.requestPersistentQuota().then(data=>console.log(data)) */ class FileStorageQuota { constructor() { let supportedTypes = [_TEMPORARY, _PERSISTENT]; this.storageQuota = navigator.storageQuota || { storages: { [_TEMPORARY]: navigator.webkitTemporaryStorage, [_PERSISTENT]: navigator.webkitPersistentStorage }, queryInfo: function (type) { return toPromise(this.storages[type].queryUsageAndQuota, this.storages[type]).then(arr => { return { usage: arr[0], quota: arr[1] } }) }, requestPersistentQuota: function (requestQuota) { return toPromise(this.storages[_PERSISTENT].requestQuota, this.storages[_PERSISTENT], requestQuota * 1024 * 1024).then(quota => { return { quota } }) }, supportedTypes } this.supportedTypes = supportedTypes this._instance = null //实例 } /** * 获得实例 */ static get instance() { return !!this._instance ? this._instance : this._instance = new FileStorageQuota() } /** * 已经分配的额度和适用查询 * @param {*类型 window.TEMPORAR(0) |window.PERSISTENT(1) } type */ queryInfo(type = window.TEMPORARY) { return new Promise((resolve, reject) => { this.storageQuota.queryInfo(this.supportedTypes[type]) .then(storageInfo => resolve({ quota: this.tansferBytes(storageInfo.quota), usage: this.tansferBytes(storageInfo.usage) })) .catch(this.errorHandler(reject)) }) } /** * 请求配额,只有PERSISTENT才需要用户允许, * 返回值是你请求的和已经分配的大值 * @param {* window.TEMPORAR(0) |window.PERSISTENT(1)} type * @param {* 请求的配额大小} requestQuota */ async requestPersistentQuota(requestQuota = 5) { let { quota: quotaM, usage } = await this.queryInfo(window.PERSISTENT) if (requestQuota > quotaM) { return new Promise((resolve, reject) => this.storageQuota.requestPersistentQuota(requestQuota * 1024 * 1024) .then(storageInfo => { return resolve({ quota: this.tansferBytes(storageInfo.quota), usage: this.tansferBytes(storageInfo.usage || usage) }) }) .catch(this.errorHandler(reject))) } return { quota: Math.max(requestQuota, quotaM), usage } } /** * 把bytes换算成KB,M,G等 * @param {* bytes的长度} bytesLength * @param {* 转为目标的单位} target */ tansferBytes(bytesLength, target = 'M') { let m = { 'Byte': 0, 'KB': 1, 'M': 2, 'G': 3 } return bytesLength / Math.pow(1024, m[target] || 0) } /** * Promise里面的错误处理 * @param {*} reject */ errorHandler(reject) { return (error) => { reject(error) } } }