javascript-HTML5 appcache,获取客户端中缓存文件的列表

在我的项目中,我尝试使用HTML5 appcache来缓存CSS和JS等静态资源,以及“用户特定”文件,例如图像和视频.当我说用户特定的图像/视频时,我试图为每个用户准备单独的文件,并且还需要控制文件下载的顺序.

在这种情况下,清单文件将为每个用户动态加载.有没有一种方法可以获取客户端中已经缓存的资源列表?

如果没有,是否可以在客户端中读取“ .appcache”文件

解决方法:

是.您可以使用AJAX请求获取清单缓存文件,然后读取它.

但是,这不能保证问题中的浏览器具有可用文件.

以下是示例代码

>哪个检查我们是否已缓存HTML5应用
>如果我们不处于缓存状态,则在清单中计算已加载的资源,并根据清单缓存条目计数(总计)显示进度条,并对所有URL进行手动AJAX GET请求以预热缓存.浏览器将自己执行此操作,但是通过这种方式,我们可以从流程中获取一些进度信息.
>当缓存处于已知良好状态时,请继续前进

免责声明:自2010年以来未经过测试可正常使用

/**
 * HTML5 offline manifest preloader.
 * 
 * Load all manifest cached entries, so that they are immediately available during the web app execution.
 * display some nice JQuery progress while loading.
 * 
 * @copyright 2010 mFabrik Research Oy
 * 
 * @author Mikko Ohtamaa, http://opensourcehacker.com
 */

/**
 * Preloader class constructor.
 * 
 * Manifest is retrieved via HTTP GET and parsed.
 * All cache entries are loaded using HTTP GET.
 * 
 * Local storage attribute "preloaded" is used to check whether loading needs to be performed,
 * as it is quite taxing operation.
 * 
 * To debug this code and force retrieving of all manifest URLs, add reloaded=true HTTP GET query parameter:
 * 
 * 
 * 
 * @param {Function} endCallback will be called when all offline entries are loaded
 * 
 * @param {Object} progressMonitor ProgressMonitor object for which the status of the loading is reported.
 */
function Preloader(endCallback, progressMonitor, debug) {

    if(!progressMonitor) {
        throw "progressMonitor must be defined";
    }

    this.endCallback = endCallback;
    this.progressMonitor = progressMonitor;
    this.logging = debug; // Flag to control console.log() output   
}

Preloader.prototype = { 
    /**
     * Load HTML5 manifest and parse its data
     * 
     * @param data: String, manifest file data
     * @return Array of cache entries 
     * 
     * @throw: Exception if parsing fails
     */
    parseManifest : function(data) {

        /* Declare some helper string functions 
         * 
         * http://rickyrosario.com/blog/javascript-startswith-and-endswith-implementation-for-strings/
         *
         */
        function startswith(str, prefix) {
            return str.indexOf(prefix) === 0;
        }

        var entries = [];

        var sections = ["NETWORK", "CACHE", "FALLBACK"];
        var currentSection = "CACHE";

        var lines = data.split(/\r\n|\r|\n/);
        var i;

        if(lines.length <= 1) {
            throw "Manifest does not contain text lines";
        }

        var firstLine = lines[0];
        if(!(startswith(firstLine, "CACHE MANIFEST"))) {
            throw "Invalid cache manifest header:" + firstLine;
        }

        for(i=1; i<lines.length; i++) {

            var line = lines[i];
            this.debug("Parsing line:" + line);

            // If whitespace trimmed line is empty, skip it
            line = jQuery.trim(line);
            if(line == "") {
                continue;
            }

            if(line[0] == "#") {
                // skip comment;
                continue;
            }

            // Test for a new section
            var s = 0;
            var sectionDetected = false;
            for(s=0; s<sections.length; s++) {
                var section = sections[s];
                if(startswith(line, section + ":")) {
                    currentSection = section;
                    sectionDetected = true;
                }
            }

            if(sectionDetected) {
                continue;
            }

            // Otherwise assume we can check for cached url
            if(currentSection == "CACHE") {
                entries.push(line); 
            }

        }

        return entries;
    },

    /**
     * Manifest is given as an <html> attribute.
     */
    extractManifestURL : function() {
        var url = $("html").attr("manifest");
        if(url === null) {
            alert("Preloader cannot find manifest URL from <html> tag");
            return null;
        }
        return url;
    },

    isPreloaded : function() {
        // May be null or false
        return localStorage.getItem("preloaded") == true;
    },

    setPreloaded : function(status) {
        localStorage.setItem("preloaded", status);
    },

    /**
     * Check whether we need to purge offline cache.
     * 
     */
    isForcedReload : function() {

        // http://www.netlobo.com/url_query_string_javascript.html
        function getQueryParam(name) {
          name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
          var regexS = "[\\?&]"+name+"=([^&#]*)";
          var regex = new RegExp( regexS );
          var results = regex.exec( window.location.href );
          if (results == null) {
            return "";
          } else {
            return results[1];
          }
        }

        if(getQueryParam("reload") == "true") {
            return true;
        }   

        return false;
    },

    /**
     * Do everything necessary to set-up offline application
     */
    load : function() {

        this.debug("Entering preloader");

        if (window.applicationCache) {
            this.debug("ApplicationCache status " + window.applicationCache.status);
            this.debug("Please see http://www.w3.org/TR/html5/offline.html#applicationcache");
        } else {
            this.silentError("The browser does not support HTML5 applicationCache object");
            return; 
        }

        var cold;

        if(this.isPreloaded()) {
            // We have succesfully completed preloading before
            // ...move forward

            forceReload = this.isForcedReload(); 
            if (forceReload == true) {
                applicationCache.update();
            } else {
                this.endCallback();
                return;
            }

            cold = false;
        } else {
            cold = true;
        }

        var url = this.extractManifestURL();
        if(url === null) {
            return;
        }

        this.progressMonitor.startProgress(cold);

        $.get(url, {}, jQuery.proxy(manifestLoadedCallback, this));

        function manifestLoadedCallback(data, textStatus, xhr) { 
            this.debug("Manifest retrieved");
            var text = data;
            manifestEntries = this.parseManifest(text); 
            this.debug("Parsed manifest entries:" + manifestEntries.length);
            this.populateCache(manifestEntries);
        }
    },


    /**
     * Bootstrap async loading of cache entries.
     * 
     * @param {Object} entrires
     */
    populateCache : function(entries) {
        this.manifestEntries = entries;
        this.currentEntry = 0;
        this.maxEntry = entries.length;
        this.loadNextEntry();
    },

    /**
     * Make AJAX request to next entry and update progress bar.
     * 
     */
    loadNextEntry : function() {

        if(this.currentEntry >= this.maxEntry) {
            this.setPreloaded(true);
            this.progressMonitor.endProgress();
            this.endCallback();
        }

        var entryURL = this.manifestEntries[this.currentEntry];
        this.debug("Loading entry: " + entryURL);

        function done() {
            this.currentEntry++;
            this.progressMonitor.updateProgress(this.currentEntry, this.maxEntries);
            this.loadNextEntry();   
        }

        this.debug("Preloader fetching:" + entryURL + " (" + this.currentEntry + " / " + this.maxEntry + ")");

        $.get(entryURL, {}, jQuery.proxy(done, this));
    },

    /**
     * Write to debug console
     * 
     * @param {String} msg
     */
    debug : function(msg) {
        if(this.logging) {
            console.log(msg);
        }
    },

    /**
     * Non-end user visible error message
     *
     * @param {Object} msg
     */
    silentError : function(msg) {
        console.log(msg);
    }
};

function ProgressMonitor() {

}

ProgressMonitor.prototype = {

    /**
     * Start progress bar... initialize as 0 / 0
     */
    startProgress : function(coldVirgin) {
        $("#web-app-loading-progress-monitor").show();
        if(coldVirgin) {
            $("#web-app-loading-progress-monitor .first-time").show();
        }
    },

    endProgress : function() {
    },

    updateProgress : function(currentEntry, maxEntries) {

    }
};

相关文章

HTML5和CSS3实现3D展示商品信息的代码
利用HTML5中的Canvas绘制笑脸的代码
Html5剪切板功能的实现
如何通过HTML5触摸事件实现移动端简易进度条
Html5移动端获奖无缝滚动动画实现
关于HTML5和CSS3实现机器猫的代码