天天看點

File System 定額(配額查詢)

不多說,在弄一個基于FileSytem/IndexedDB的小應用,目前處于基礎開發階段,

我們在使用FileSystem的時候無疑是需要知道浏覽器的定額(配額的),怎麼去查詢,當然可以查詢 

Quota Management API

個人覺得還是略有複雜,為了避免不停的then,同時更少的關注内部的差別,再簡單包裝了一下。

不多說,代碼:

/**
 * 參考的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)
        }
    }
}      

測試:

FileStorageQuota.instance.queryInfo().then(data=>console.log(data))

Object {quota: 2767.7421379089355, usage: 22.347068786621094}
      

  

FileStorageQuota.instance.requestPersistentQuota().then(data=>console.log(data))

Object {quota: 10240, usage: 0}      

源碼位址:

https://github.com/xiangwenhu/BlogCodes/tree/master/client/FileSystem

參考:

StorageQuota - Web APIs | MDN