♠ 写在前面
小程序网络图片读取:
- 在读取OSS图片CDN分发时流量大量消耗,导致资金费用增加。
- 网络图片比较大时,图片加载缓慢。
为了尽量减少上面两个问题,所以对已读的图片进行缓存处理,减少多次访问不必要的流量消耗。
♠ 小程序的文件系统
文件主要分为两大类:
- 代码包文件:代码包文件指的是在项目目录中添加的文件。
- 本地文件:通过调用接口本地产生,或通过网络下载下来,存储到本地的文件。
其中本地文件又分为三种:
- 本地临时文件:临时产生,随时会被回收的文件。不限制存储大小。
- 本地缓存文件:小程序通过接口把本地临时文件缓存后产生的文件,不能自定义目录和文件名。跟本地用户文件共计,普通小程序最多可存储 10MB,游戏类目的小程序最多可存储 50MB。
- 本地用户文件:小程序通过接口把本地临时文件缓存后产生的文件,允许自定义目录和文件名。跟本地缓存文件共计,普通小程序最多可存储 10MB,游戏类目的小程序最多可存储 50MB。
而我们要使用的文件缓存方式就是 本地临时文件 。
♠ 实现原理
图片缓存流程:
- 将要图片/文件通过
wx.downloadFile(Object object)
下载到本地,成为本地临时文件。 - 使用小程序的Storage记录网络地址和本地地址,做映射。
- 使用时,在Storage读取映射表。如果存在本地文件,并通过
FileSystemManager.accessSync(string path)
判断文件存在,则读取本地地址;不存在,删除该映射。
♠ 注意
- 图片缓存只针对多次访问的图片,请按照实际情况调用。如果访问一次的也做,CDN流量消耗反倒翻倍,得不偿失。
- 小程序缓存最大10M。为防止将缓存写满,小程序初始化时,如果超过1000条,清空缓存记录,重新开始。
- 1000条。该数不是固定数字,请根据自己的实际情况自定。如果你本身就会往Storage放数据,请自行判断需要多少条,不要导致其他数据无法存入,影响其他功能正常使用。
- 为什么不用LRU最近使用删除?没必要。1000本身是个虚数,留存
1~2M
做其他代码备用,而文件异步保存,本身会导致有好多文件无法检测到,如果通过循环去判断最近时间,太耗费性能,还不如进入小程序时,直接清空,从头开始。小程序本身是轻量级的,一段时间清空一次即可。
♠ 代码
const fileSystem = wx.getFileSystemManager()
const getStorageImage = (web_image) => {
let webImages = wx.getStorageSync('webImages') || []
let webImage = webImages.find(y => y.web_path === web_image)
if (webImage) {
try {
fileSystem.accessSync(webImage.local_path)
return webImage.local_path
} catch(e) {
let webImageIdx = webImages.findIndex(y => y.web_path === web_image)
webImages.splice(webImageIdx, 1)
wx.setStorageSync('webImages', webImages)
}
} else {
wx.downloadFile({
url: web_image,
success (res) {
if (res.statusCode === 200) {
let filePath = res.tempFilePath
let webImageStorage = wx.getStorageSync('webImages') || []
let storage = {
web_path: web_image,
local_path: filePath,
last_time: Date.parse(new Date()),
}
webImageStorage.push(storage)
wx.setStorageSync('webImages', webImageStorage)
}
}
})
}
return web_image
}
module.exports = {
getStorageImage
}
♠ 写在后面
本文参照博客
https://juejin.im/post/5b42d3ede51d4519277b6ce3
(幽蛰 写于 2020.06.10)