• 图片下载本地缓存时间戳显示图片方法


    来源:http://ask.dcloud.net.cn/article/511

    源码下载 

    参考文章
    http://ask.dcloud.net.cn/article/256
    http://ask.dcloud.net.cn/article/397

    说明:为了方便,里面使用的图片来源是从上面文章中的源码项目获取的.
    说明:参考了上面文章中的思路,然后自己重新写了一个较为完整的图片本地缓存显示工具.
    功能
    1.第一次显示图片时下载到本地,然后之后如果本地存在缓存(根据url),则显示本地缓存的图片
    2. 基于plus的storage,对每一个图片的缓存进行控制管理,增加时间戳参数,来控制本地缓存的有效时间
    3. 将所有的下载任务放入队列中,进行统一下载管理,增加最大并发请求数,防止一次性请求过多损耗性能
    4. 加入了图片缓存池机制,对于同一个下载路径的图片不会多次下载,而是填入缓存池,下载后统一回调
    5. 修改了图片本地路径的获取方法,摆脱第三方依赖
    6. 重构了代码,并入开发框架中

    使用方法

    * 外部API:注意,需要显示的图片需要有data-img-localcache这个属性(用来放目标url),dom需要是原生对象
     * 清除所有图片缓存:MobileFrame.ImageUtil.ImageLoaderFactory.clearLoaderImgsCache(successCb,errorCb)
     * 采取本地缓存显示所有图片:MobileFrame.ImageUtil.ImageLoaderFactory.setAllNetImgsWithLocalCache();
     * 清除某一张图片的本地缓存:MobileFrame.ImageUtil.ImageLoaderFactory.clearNetUrlImgCache(src);
     * 显示某一张图片:MobileFrame.ImageUtil.ImageLoaderFactory.setImgWidthLocalCache(dom,src);

    源码

    /**
     * @description   移动开发框架
     * @author dailc  dailc 
     * @version 1.0
     * @time 2016-01-11 16:57:57
     * 功能模块:只依赖于plus系统
     * @see http://ask.dcloud.net.cn/people/%E6%92%92%E7%BD%91%E8%A6%81%E8%A7%81%E9%B1%BC
     * 图片本地缓存模块********************************
     * 1.本地缓存显示图片
     * 2.增加storage,增加每一个本地缓存的有效时间戳
     * 3.增加自定义设置方法,可以根据不同需求,对参数进行修改
     * 4.采用下载队列进行下载管理,增加最大并发请求数,防止一次性请求过多损耗性能
     * 5.修改了图片本地路径的获取方法,摆脱第三方依赖
     * 6.重构代码
     * 外部API:注意,需要显示的图片需要有data-img-localcache这个属性(用来放目标url)
     * 清除所有图片缓存:MobileFrame.ImageUtil.ImageLoaderFactory.clearLoaderImgsCache(successCb,errorCb)
     * 采取本地缓存显示所有图片:MobileFrame.ImageUtil.ImageLoaderFactory.setAllNetImgsWithLocalCache();
     * 清除某一张图片的本地缓存:MobileFrame.ImageUtil.ImageLoaderFactory.clearNetUrlImgCache(src);
     * 显示某一张图片:MobileFrame.ImageUtil.ImageLoaderFactory.setImgWidthLocalCache(dom,src);
     * 图片本地缓存模块完毕********************************
     */
    (function(global) {
        /**
         * 定义全局函数对象 define出来的
         */
        var mapping = {};
        /**
         * 缓存,正在用到的对象,函数中return 出来的,这样就不需要重复执行函数
         */
        var cache = {};
        /**
         * @description 模块定义
         * @param {String} id id
         * @param {Function} func 对应的函数对象
         */
        global.define = function(id, func) {
            mapping[id] = func;
        };
        /**
         * @description 生成模块对象,并采用本地缓存
         * @param {String} id
         */
        global.require = function(id) {
            if (!/.js$/.test(id)) {
                id += '.js';
            }
            if (cache[id]) {
                return cache[id];
            } else {
                return cache[id] = mapping[id]({});
            }
        };
        /**
         * @description 配置全局工具类以及一些需要用到的全局函数
         */
        (function() {
            global.MobileFrame = {};
            /**
             * 空函数
             */
            MobileFrame.noop = function() {};
            /**
             * @description each遍历操作
             * @param {type} elements
             * @param {type} callback
             * @returns {global}
             */
            MobileFrame.each = function(elements, callback, hasOwnProperty) {
                if (!elements) {
                    return this;
                }
                if (typeof elements.length === 'number') {
                    [].every.call(elements, function(el, idx) {
                        return callback.call(el, idx, el) !== false;
                    });
                } else {
                    for (var key in elements) {
                        if (hasOwnProperty) {
                            if (elements.hasOwnProperty(key)) {
                                if (callback.call(elements[key], key, elements[key]) === false) return elements;
                            }
                        } else {
                            if (callback.call(elements[key], key, elements[key]) === false) return elements;
                        }
                    }
                }
                return global;
            };
            /**
             * @description plusReady
             * @param {Function} callback
             * @returns {global} 返回的是global
             */
            MobileFrame.plusReady = function(callback) {
                if (window.plus) {
                    setTimeout(function() { //解决callback与plusready事件的执行时机问题(典型案例:showWaiting,closeWaiting)
                        callback();
                    }, 0);
                } else {
                    document.addEventListener("plusready", function() {
                        callback();
                    }, false);
                }
                return global;
            };
            /**
             * @description 得到相对路径对应的key,这个key可以使缓存池的或者是本地缓存键值
             * 主要作用是去除非法字符
             * @param {String} relativePath
             */
            MobileFrame.getRelativePathKey = function(relativePath) {
                var finalKey =
                    //                  relativePath.replace('/', '').replace('.', '').replace('/', '')
                    //                  .replace('_download', '').replace('jpg', '');
                    relativePath.replace(/[&|\*^%$#@-]/g, "");
                return finalKey;
            };
            /**
             * @description 更改url类型,去除cache,因为cache会造成一些困扰
             * @param {String} url 传入的url
             */
            MobileFrame.changImgUrlTypeNoCache = function(url) {
                url = url || '';
                if (url.indexOf('?') != -1) {
                    url += '&timeRandKey=' + Math.random();
                } else {
                    url += '?timeRandKey=' + Math.random();
                }
                return url;
            };
            /**
             * @description 删除指定路径的文件
             * @param {String} relativePath  绝对路径或相对路径例如:  _downloads/imgs/test.jpg
             * @param {Function} successCallback  删除成功回调
             * @param {Function} errorCallback  失败回调
             */
            MobileFrame.delFile = function(relativePath, successCallback, errorCallback) {
                if (!relativePath) {
                    return;
                }
                MobileFrame.plusReady(function() {
                    plus.io.resolveLocalFileSystemURL(relativePath, function(entry) {
                        entry.remove(function(entry) {
                            if (successCallback && typeof(successCallback) == 'function') {
                                successCallback(true);
                            }
                        }, function(e) {
                            if (errorCallback && typeof(errorCallback) == 'function') {
                                errorCallback('删除文件失败!');
                            }
                        });
                    }, function() {
                        if (errorCallback && typeof(errorCallback) == 'function') {
                            errorCallback('打开文件路径失败!');
                        }
                    });
                });
            };
            /**
             * @description 判断网络状态
             */
            function GetNetWorkState() {
                var NetStateStr = '未知';
                var types = {};
                types[plus.networkinfo.CONNECTION_UNKNOW] = "未知";
                types[plus.networkinfo.CONNECTION_NONE] = "未连接网络";
                types[plus.networkinfo.CONNECTION_ETHERNET] = "有线网络";
                types[plus.networkinfo.CONNECTION_WIFI] = "WiFi网络";
                types[plus.networkinfo.CONNECTION_CELL2G] = "2G蜂窝网络";
                types[plus.networkinfo.CONNECTION_CELL3G] = "3G蜂窝网络";
                types[plus.networkinfo.CONNECTION_CELL4G] = "4G蜂窝网络";
                NetStateStr = types[plus.networkinfo.getCurrentType()];
    
                return NetStateStr;
            };
            /**
             * @description 判断是否有网络
             */
            MobileFrame.IsNetWorkCanUse = function() {
                var IsCanUseNetWork = false;
                if (GetNetWorkState() == '未知' || GetNetWorkState() == '未连接网络') {
                    IsCanUseNetWork = false;
                } else {
                    IsCanUseNetWork = true;
                }
                return IsCanUseNetWork;
            };
        })();
        /**
         * @description 定义模块功能-图片工具类
         */
        define('scripts/Core/ImageUtil.js', function(exports) {
            /**
             * @description 图片加载工厂,包含图片加载方法
             * 例如:时间戳控制缓存,下载队列批次下载,默认图片,下载loading图片,下载失败图片
             * 注意相对路径在Android:/sdcard/Android/data/io.dcloud.HBuilder/.HBuilder/...
             * iOS:/Library/Pandora/...
             */
            (function(ImgLoaderFactory) {
                /**
                 * 默认的options
                 */
                var defaultSettingOptions = {
                    //默认的图片缓存目录-存到应用的downloads/imgs下
                    'imgStoragePath': "_downloads/imgs/",
                    //默认图片的基座路径
                    'defaultImgBase': '../../img/mobileFrame/',
                    //loading图片的名称
                    'loadingImgName': 'img_loading.jpg',
                    //error图片名称
                    'errorImgName': 'img_error.jpg',
                    //图片缓存的时间戳,毫秒单位,默认为1天
                    'imgsTimeStamp': 1000 * 60 * 60 * 24 * 1,
                    //同时最多的downloader 并发下载数目,默认为3个
                    'concurrentDownloadCount': 3,
                    //单个下载任务最大的请求时间,防止一些机型上无法触发错误回调,单位毫秒,默认10秒
                    'maxTimeSingleDownloadTaskSpend': 1000 * 10
                };
                //默认的下载图片临时变量
                var defaultLoadingImg = defaultSettingOptions['defaultImgBase'] + defaultSettingOptions['loadingImgName'];
                //默认的显示图片临时变量
                var defaultImg = defaultSettingOptions['defaultImgBase'] + defaultSettingOptions['errorImgName'];
                /**
                 * 图片缓存的session头部
                 */
                var imageSessionKey_header = 'imageSessionKey_util_imgs_';
                /**
                 * 图片缓存的session的管理者
                 */
                var imageSessionManagerKey = 'imageSessionKey_util_Manager';
                /**
                 * 图片缓存池,用来解决多张图片并发请求问题
                 * 默认是空的,当有多张图片是同一个请求时,缓存池子中会有数据
                 * 格式  {'url1':[dom1,dom2]}
                 */
                var requestImgsPool = {};
                /**
                 * 并发下载任务,包括下载队列,处理最大并发数下载
                 */
                var concurrentDownloadTask = {
                    //任务池-还没有下载的任务
                    Queue: [],
                    //当前正在下载的任务数量
                    CurrentTaskCount: 0
                };
                /**
                 * 当前的任务队列,包含任务的名称,以及时间戳-用来控制最大的超时时间,防止不能正常触发回调
                 * 包含:
                 * taskObj,timeBegin
                 * 格式:{url1:{task1,time1}}
                 */
                var currentDownloadTasks = {};
                /**
                 * @description 将对应的图片缓存键值添加进入图片缓存管理中
                 * @param {String} key 图片路径对应的key
                 */
                function addImageSessionKeyToManager(key) {
                    //获取管理者
                    var manager = plus.storage.getItem(imageSessionManagerKey);
                    if (manager == null) {
                        //如果以前的缓存为空,生成缓存
                        manager = [];
                    } else {
                        try {
                            manager = JSON.parse(manager);
                        } catch (e) {}
                    }
                    if (manager.indexOf(key) == -1) {
                        manager.push(key);
                    }
                    plus.storage.setItem(imageSessionManagerKey, JSON.stringify(manager));
                };
                /**
                 * @description 从缓存管理中移除相应的图片缓存
                 * @param {String} key 图片路径对应的key
                 */
                function removeImageSessionKeyFromManager(key) {
                    //获取管理者
                    var manager = plus.storage.getItem(imageSessionManagerKey);
                    if (manager == null) {
                        //这时候肯定没有离线缓存
                        return;
                    }
                    try {
                        manager = JSON.parse(manager);
                    } catch (e) {}
                    var index = -1;
                    for (var i = 0; i < manager.length || 0; i++) {
                        if (manager[i] == key) {
                            index = i;
                        }
                    }
                    if (index != -1) {
                        //删除对应的index位置
                        manager.splice(index, 1);
                        //重新存储
                        plus.storage.setItem(imageSessionManagerKey, JSON.stringify(manager));
                    }
                };
    
                /**
                 * 设置图片缓存key
                 * @param {String} url
                 * @param {JSON} value 存进去的是图片相关的所有属性,包括时间戳,本地路径等
                 */
                function setImageSessionItem(url, value) {
                    if (url == null) {
                        return;
                    }
                    //然后添加进入缓存管理者中
                    addImageSessionKeyToManager(url);
                    url = imageSessionKey_header + MobileFrame.getRelativePathKey(url);
                    value = (value != null) ? value : '';
                    value = (typeof(value) == 'string') ? value : JSON.stringify(value);
                    plus.storage.setItem(url, value);
    
                };
                /**
                 * 获取图片缓存key
                 * @param {String} url
                 * @return {JSON} item 返回的是一个json对象,包括图片相关的所有属性,包括时间戳,本地路径等
                 * @example 包含属性:time localPath
                 */
                function getImageSessionItem(url) {
                    if (url == null) {
                        return null;
                    }
                    //去除非法字符
                    url = imageSessionKey_header + MobileFrame.getRelativePathKey(url);
                    var item = plus.storage.getItem(url);
                    try {
                        if (item != null) {
                            item = JSON.parse(item);
                        }
                    } catch (e) {}
                    return item;
                };
                /**
                 * 移除图片缓存key
                 * @param {String} url
                 */
                function removeImageSessionItem(url) {
                    if (url == null) {
                        return null;
                    }
                    removeImageSessionKeyFromManager(url);
                    //去除非法字符
                    url = imageSessionKey_header + MobileFrame.getRelativePathKey(url);
                    var items = plus.storage.removeItem(url);
                };
                /**
                 * @description 设置图片的src地址,根据一个url,为所有需要的图片赋值
                 * @param {HTMLElement} $img 图片的dom,这里为原生dom对象
                 * @param {String} srcUrl 图片的路径
                 * @param {String} relativePath 相对路径,用来判断缓存池的
                 */
                function setImgSrc($img, srcUrl, relativePath) {
                    if (!srcUrl) {
                        return;
                    }
                    setImgSrcByDom($img, srcUrl);
                    //如果缓存池子中存在图片
                    if (!relativePath) {
                        return;
                    }
                    var relativePathKey = MobileFrame.getRelativePathKey(relativePath);
                    if (requestImgsPool && requestImgsPool[relativePathKey]) {
                        var imgsData = requestImgsPool[relativePathKey];
                        //如果是数组
                        if (Array.isArray(imgsData)) {
                            for (var i = 0; i < imgsData.length; i++) {
                                setImgSrcByDom(imgsData[i], srcUrl);
                            }
                        } else {
                            //单条数据--单个dom对象
                            setImgSrcByDom(imgsData, srcUrl);
                        }
                        if (srcUrl != defaultLoadingImg) {
                            //如果不是loading图片就清空
                            //清空图片池子中的该条键值
                            requestImgsPool[relativePathKey] = null;
                        }
                    }
                };
                /**
                 * @description 设置图片的src地址,一个dom和一个 src一一对应
                 * @param {HTMLElement} $img 图片的dom,原生dom对象
                 * @param {String} srcUrl 图片的路径
                 */
                function setImgSrcByDom($img, srcUrl) {
                    if (!$img || !($img instanceof HTMLElement)) {
                        //console.log('该dom不是原生对象,url:' + srcUrl);
                        return;
                    }
                    //暂时去除loading图片的独特样式
    //              if (srcUrl == defaultLoadingImg) {
    //                  //默认的loading图片,修改css
    //                  $img.style.maxWidth = '30px';
    //                  $img.style.maxHeight = '30px';
    //              } else {
    //                  //恢复普通高度
    //                  $img.style.maxWidth = '100%';
    //                  $img.style.maxHeight = '100%';
    //              }
                    srcUrl = MobileFrame.changImgUrlTypeNoCache(srcUrl);
                    $img.setAttribute('src', srcUrl);
                };
                /**
                 * @description 移除所有的图片缓存键
                 */
                function clearAllImageSessionKey() {
                    MobileFrame.plusReady(function() {
                        var manager = plus.storage.getItem(imageSessionManagerKey);
                        if (manager == null) {
                            //这时候肯定没有离线缓存
                            return;
                        }
                        try {
                            manager = JSON.parse(manager);
                        } catch (e) {}
                        if (Array.isArray(manager)) {
                            for (var i = 0; i < manager.length; i++) {
                                removeImageSessionItem(manager[i]);
                            }
                        }
                    });
    
                };
                /**
                 * @description 设置图片加载工具的一些基本参数
                 * @param {JSON} options 参数
                 * @example 参数没传代表使用默认值,包括:
                 * imgStoragePath,string型,图片的默认路径
                 * defaultImgBase,string型,默认图片的基座路径
                 */
                ImgLoaderFactory.setOptions = function(options) {
                    if (!options) {
                        return;
                    }
                    //设置参数
                    for (var key in defaultSettingOptions) {
                        //如果设置的是有效的
                        if (options[key] != null) {
                            defaultSettingOptions[key] = options[key];
                        }
                    }
                    //默认的下载图片临时变量
                    defaultLoadingImg = defaultSettingOptions['defaultImgBase'] + defaultSettingOptions['loadingImgName'];
                    //默认的显示图片临时变量
                    defaultImg = defaultSettingOptions['defaultImgBase'] + defaultSettingOptions['errorImgName'];
                };
                /**
                 * @description 清除图片加载工厂的所有图片缓存
                 * @param {Function} successCallback 成功回调
                 * @param {Function} errorCallback 失败回调
                 */
                ImgLoaderFactory.clearLoaderImgsCache = function(successCallback, errorCallback) {
                    MobileFrame.plusReady(function() {
                        //遍历目录文件夹下的所有文件,然后删除
                        var tmpUrl = plus.io.convertLocalFileSystemURL(defaultSettingOptions['imgStoragePath']);
                        //需要手动加上 file://
                        tmpUrl = 'file://' + tmpUrl;
                        //同时清除所有的缓存键值
                        clearAllImageSessionKey();
                        plus.io.resolveLocalFileSystemURL(tmpUrl, function(entry) {
                            entry.removeRecursively(function() {
                                if (successCallback && typeof(successCallback) == 'function') {
                                    successCallback('清除图片缓存成功!');
                                }
                            }, function() {
                                if (errorCallback && typeof(errorCallback) == 'function') {
                                    errorCallback('清除图片缓存失败!');
                                }
                            });
                        }, function(e) {
                            if (errorCallback && typeof(errorCallback) == 'function') {
                                errorCallback('打开图片缓存目录失败!');
                            }
                        });
                    });
                };
                /**
                 * @description 从一个网络URL中,获取本地图片缓存相对路径
                 * @param {String} loadUrl 图片的网络路径,如果为null,则返回一个null
                 * @return {String} 返回路径或者是 ***outOfTime***表示缓存时间戳过去
                 * @example 获取相对路径可以有很多种方法
                 * 比如可以用md5将url加密,或者其它字符串操作等等
                 * 我这里也是根据项目而进行自适应的
                 */
                ImgLoaderFactory.getRelativePathFromLoadUrl = function(loadUrl) {
                    if (loadUrl == null) return null;
                    //如果loadUrl以../开头,代表是相对路径,采用本地相对路径,这里就直接返回本地路径,这样就是直接赋值了
                    if (loadUrl.substring(0, 5).indexOf('../') != -1) {
                        return loadUrl;
                    }
                    //图片缓存如果存在,判断是否过期,默认为''
                    var isOutOfTimeHeader = '';
                    //如果存在本地缓存,并且没有过期,采用本地缓存中的图片
                    var loacalImgSessionItem = getImageSessionItem(loadUrl);
                    if (loacalImgSessionItem != null) {
                        //判断是否过期  time localPath
                        if (loacalImgSessionItem.time) {
                            loacalImgSessionItem.time = parseInt(loacalImgSessionItem.time, 10);
                            if ((new Date()).valueOf() - loacalImgSessionItem.time > defaultSettingOptions['imgsTimeStamp']) {
                                //console.log('当前缓存已经过期')
                                //返回一个特殊字符,代表过期 
                                isOutOfTimeHeader = '***outOfTime***';
                            } else {
                                //console.log('缓存未过期');
                            }
                        }
                        if (loacalImgSessionItem.localPath) {
                            return loacalImgSessionItem.localPath;
                        }
                    }
                    //获取图片后缀,如果没有获取到后缀,默认是jpg
                    var imgSuffix = loadUrl.substring(loadUrl.lastIndexOf(".") + 1, loadUrl.length);
                    if (
                        imgSuffix.toLocaleLowerCase() != ("jpg") &&
                        imgSuffix.toLocaleLowerCase() != ("jpeg") &&
                        imgSuffix.toLocaleLowerCase() != ("png") &&
                        imgSuffix.toLocaleLowerCase() != ("bmp") &&
                        imgSuffix.toLocaleLowerCase() != ("svg") &&
                        imgSuffix.toLocaleLowerCase() != ("gif")
                    ) {
                        //如果后缀没有包含以上图片,将后缀改为jpg
                        imgSuffix = 'jpg';
                    }
                    //更换存储方式,变为将整个路径存储下来,然后去除非法字符
                    var regIllegal = /[&|\*^%$#@-:.?/=!]/g;
                    //获取图片名字
                    var imgName = loadUrl.replace(regIllegal, '');
                    //最终的名字
                    var filename = imgName + '.' + imgSuffix;
                    //console.log('loadurl:'+loadUrl+',fileName:'+filename);
                    var relativePath = defaultSettingOptions['imgStoragePath'] + filename;
                    setImageSessionItem(loadUrl, {
                        'localPath': relativePath,
                        'time': (new Date()).valueOf()
                    });
                    //将是否过期标识传出
                    return isOutOfTimeHeader + relativePath;
                };
    
                /**
                 * @description 删除某一张网络图片的本地缓存,同时也会删除缓存键值
                 */
                ImgLoaderFactory.clearNetUrlImgCache = function(netImgUrl, successCallback, errorCallback) {
                    MobileFrame.plusReady(function() {
                        //删除该键值对应的缓存
                        removeImageSessionItem(netImgUrl);
                        MobileFrame.delFile(ImgLoaderFactory.getRelativePathFromLoadUrl(netImgUrl), successCallback, errorCallback);
                    });
                };
    
                /**
                 * @description 给指定的图片dom 设置本地图片属性
                 * @param {HTMLElement} $img 目标图片dom,这里为原生的dom对象
                 * @param {String} relativePath 本地图片路径
                 */
                function setImgFromLocalCache($img, relativePath) {
                    /*例如:
                     * 本地相对路径("downloads/imgs/logo.jpg")转成SD卡绝对路径
                     * 例如相对路径:downloads/imgs/logo.jpg
                     * ("/storage/emulated/0/Android/data/io.dcloud.HBuilder/.HBuilder/downloads/imgs/logo.jpg");
                     * */
                    if (!relativePath) {
                        return;
                    }
                    MobileFrame.plusReady(function() {
                        var sd_path = plus.io.convertLocalFileSystemURL(relativePath);
                        setImgSrc($img, sd_path, relativePath);
                    });
                };
                /**
                 * @description 通过本地缓存的方法显示网络图片
                 * @param {HTMLElement} $img 原生dom对象
                 * @param {String} loadUrl loadurl
                 */
                ImgLoaderFactory.setImgWidthLocalCache = function($img, loadUrl) {
                    if ($img == null || loadUrl == null) return;
                    MobileFrame.plusReady(function() {
                        var relativePath = ImgLoaderFactory.getRelativePathFromLoadUrl(loadUrl);
                        //判断需不需要将路径进行编码,如果是中文路径,需要编码后才能下载
                        var regChinese = /[u4E00-u9FA5]/g;
                        var tmpLoadUrl = loadUrl.replace(regChinese, 'chineseRemoveAfter');
                        if (tmpLoadUrl.indexOf('chineseRemoveAfter') != -1) {
                            loadUrl = encodeURI(loadUrl);
                        }
                        //判断是否已经缓存过期
                        var isCacheOutOfTime = false;
                        if (relativePath.indexOf('***outOfTime***') != -1) {
                            relativePath.replace('***outOfTime***', '');
                            isCacheOutOfTime = true;
                        }
                        if (relativePath == 'default.jpg') {
                            //设置默认图片
                            setImgSrc($img, defaultImg);
                        } else {
                            if (isCacheOutOfTime == false) {
                                //检查图片是否已存在
                                plus.io.resolveLocalFileSystemURL(relativePath, function(entry) {
                                    //如果文件存在,则直接设置本地图片
                                    setImgFromLocalCache($img, relativePath);
                                }, function(e) {
                                    readyToGetNetImg($img, loadUrl, relativePath);
                                });
                            } else {
                                //否则,本地缓存已经过期,直接网络获取
                                readyToGetNetImg($img, loadUrl, relativePath);
                            }
                        }
                    });
                };
                /**
                 * @description 准备通过网络获取图片
                 * @param {HTMLElement} $img 原生dom对象
                 * @param {String} loadUrl loadurl
                 * @param {String} relativePath 本地相对路径
                 */
                function readyToGetNetImg($img, loadUrl, relativePath) {
                    //如果文件不存在,上网下载
                    if (MobileFrame.IsNetWorkCanUse() == true) {
                        //添加进入图片缓存池中
                        var relativePathKey = MobileFrame.getRelativePathKey(relativePath);
                        if (requestImgsPool && requestImgsPool[relativePathKey] && Array.isArray(requestImgsPool[relativePathKey])) {
                            //如果已经存在该条图片缓存池,代表这条资源已经进行请求了,只需要填进响应池子即可
                            //console.log('已经存在缓存池:'+loadUrl);
                            requestImgsPool[relativePathKey].push($img);
                            //设置一张加载中图片,这只是假象,其实并没有下载
                            setImgSrc($img, defaultLoadingImg);
                            return;
                        } else {
                            //新建缓存池
                            //console.log('新建缓存池:'+loadUrl);
                            requestImgsPool[relativePathKey] = [];
                            requestImgsPool[relativePathKey].push($img);
                        }
                        //如果网络状态能用,联网下载图片
                        setImgFromNet($img, loadUrl, relativePath);
                    } else {
                        //采用本地默认图片
                        setImgSrc($img, defaultImg);
                    }
                };
                /**
                 * @description 从网络下载图片,并给指定的img dom赋值
                 * @param {HTMLElement} $img 目标img 原生dom
                 * @param {String} loadUrl 网络图片路径
                 * @param {String} relativePath 图片下载后的本地路径,如果不指定,采用默认值 在_downloads/imgs/下
                 */
                function setImgFromNet($img, loadUrl, relativePath) {
                    relativePath = (typeof(relativePath) == 'string' && relativePath != '') ? relativePath : ImgLoaderFactory.getRelativePathFromLoadUrl(loadUrl);
                    //下载参数
                    var options = {
                        filename: relativePath,
                        timeout: 3,
                        retryInterval: 3
                    };
                    //解决ios的网络缓存问题
                    loadUrl = MobileFrame.changImgUrlTypeNoCache(loadUrl);
                    //1.将图片 设为默认的下载图片
                    setImgSrc($img, defaultLoadingImg);
                    //2.创建下载任务
                    var dtask = plus.downloader.createDownload(loadUrl,
                        options,
                        function(d, status) {
                            if (status == 200) {
                                //下载成功
                                //console.log('绝对路径:'+d.filename);
                                //这里传入的是相对路径,方便缓存显示
                                setImgFromLocalCache($img, relativePath);
                            } else {
                                //下载失败,需删除本地临时文件,否则下次进来时会检查到图片已存在
                                //console.log("下载失败=" + status + "==" + relativePath);
                                //dtask.abort();//文档描述:取消下载,删除临时文件;(但经测试临时文件没有删除,故使用delFile()方法删除);
                                if (relativePath != null) {
                                    MobileFrame.delFile(relativePath);
                                }
                                setImgSrc($img, defaultImg);
                            }
                            //下载完成,当前任务数-1,并重新检查下载队列
                            concurrentDownloadTask['CurrentTaskCount']--;
                            //下载完成,从当前下载队列中去除
                            currentDownloadTasks[dtask.url] = null;
                            executeDownloadTasks();
                        });
                    //3.启动下载任务,添加进入下载队列中
                    concurrentDownloadTask['Queue'].push(dtask);
                    //执行并发下载队列
                    executeDownloadTasks();
                };
                /**
                 * @description 执行下载任务,通过队列中一个一个的进行
                 */
                function executeDownloadTasks() {
                    //console.log('检查下载队列');
                    //先检查是否存在任务超时的
                    for (var taskItem in currentDownloadTasks) {
                        if (currentDownloadTasks[taskItem] &&
                            currentDownloadTasks[taskItem].timeBegin && (new Date()).valueOf() - currentDownloadTasks[taskItem].timeBegin > defaultSettingOptions['maxTimeSingleDownloadTaskSpend']) {
                            //如果当前下载人已经超时,并且没有自动触发回调
                            //终止任务下载
                            currentDownloadTasks[taskItem].taskObj && currentDownloadTasks[taskItem].taskObj.abort&&currentDownloadTasks[taskItem].taskObj.abort();
                            concurrentDownloadTask['CurrentTaskCount']--;
                            //从当前任务队列中去除
                            currentDownloadTasks[taskItem] = null;
                            //console.log('存在超时的任务,手动剔除');
                        }
                    }
                    //如果当前下载任务小于并发下载数       
                    if (concurrentDownloadTask['CurrentTaskCount'] < defaultSettingOptions['concurrentDownloadCount']) {
                        if (concurrentDownloadTask['Queue'].length > 0) {
                            //开启一个下载任务
                            var nowTask = concurrentDownloadTask['Queue'].shift();
                            nowTask.start()
                                //当前任务数++
                            concurrentDownloadTask['CurrentTaskCount']++;
                            currentDownloadTasks[nowTask.url] = {
                                taskObj: nowTask,
                                timeBegin: (new Date()).valueOf()
                            }
                            //console.log('添加一个下载任务');
                        }else{
                            //console.log('已经没有了下载任务');
                        }
                    }else{
                        //console.log('已经达到最大下载数量,延迟下载');
                    }
                };
                /**
                 * @description 设置页面中的所有图片(本地缓存方式)
                 * 注意,只有存在data-img-localcache 标签的图片才会有效果
                 */
                ImgLoaderFactory.setAllNetImgsWithLocalCache = function() {
                    //获取页面中所有的图片
                    var imgs = document.querySelectorAll('img');
                    MobileFrame.each(imgs, function(key, value) {
                        var src = this.getAttribute('data-img-localcache');
                        //console.log('显示图片:' + src);
                        if (src != null && src != '') {
                            ImgLoaderFactory.setImgWidthLocalCache(this, src);
                        }
                    });
                };
            })(exports.ImageLoaderFactory = {});
    
            return exports;
        });
        /**
         * 生成模块
         */
        {
            MobileFrame.ImageUtil = require('scripts/Core/ImageUtil.js');
        }
    
    })(this);

    截图1

    截图2

    截图3

  • 相关阅读:
    单精度和双精度
    @Transactional注解用法
    JPA No EntityManager with actual transaction available for current thread
    上传文件Request Entity Too Large解决办法
    PG数据库查看当前会话和结束会话
    Chrome浏览器记不住密码也不提示保存密码win10
    ARM平台VMP保护开发入门
    关于我
    HDU7072:Boring data structure problem——题解
    HDU7067:Just another board game——题解
  • 原文地址:https://www.cnblogs.com/lizeyan/p/5549048.html
Copyright © 2020-2023  润新知