目录

小程序实现本地图片缓存功能

目录

小程序实现本地图片缓存功能

https://img-home.csdnimg.cn/images/20240715101418.png

关键词由CSDN通过智能技术生成

公司最近有个需求,就是我们的小程序的详情页一点开就是好几十张图片,特别浪费流量,而且不够快。于是就想,能不能把上次加载的图片存在本地,等下次打开的时候直接加载本地图片就可以了?

事实证明是可行的。

新建一个upImg.js文件,把所有的功能都写在里面。


const fs = wx.getFileSystemManager();

//入口方法
function chekcimgstorsize(warrantyId, data) {
return new Promise((resolve, reject) => {
let imgStor = wx.getStorageSync('imgStor') || [];
let aIndex = imgStor.findIndex((item) => {
return item.warrantyId == warrantyId;
})
if (aIndex == -1) { //没找到
resolve(data);
isOver(data).then((res) => {
let imgStor = wx.getStorageSync('imgStor') || [];
imgStor.push({
warrantyId: warrantyId,
data: res
});
wx.setStorageSync("imgStor", imgStor);
})
} else { //找到了
console.log("我是有缓存了");
if(imgStor[aIndex].data){  
 let data2 = imgStor[aIndex].data;
let data1 = JSON.parse(JSON.stringify(data));
for(let i=0;i<data2.length;i++){
for(let j=0;j<data1.length;j++){
if(data2[i].detectId === data1[j].detectId && data2[i].imgurl === data1[j].imgurl){
data1[j].imgurl = data2[i].ImgSave;
data1[j].isSave = 1;
}
}
}
resolve(data1);
let additionalArr = data1.filter((item)=>{
return !item.isSave && item.imgurl
})
if(additionalArr.length>0){
downloadImg(additionalArr).then((res)=>{
let bimgStor = wx.getStorageSync('imgStor') || [];
let bIndex = imgStor.findIndex((item) => {
return item.warrantyId == warrantyId;
})
for(let k = 0;k<res.length;k++){
bimgStor[bIndex].data.push(res[k])
}
wx.setStorageSync("imgStor", bimgStor);
})
}  
 }else{
console.log("没下载完就退了,缓存里没有!")
}
}
})
}

// 先看缓存是否快满了,快满了去删;不然去下载
function isOver(data) {
return new Promise((resolve, reject) => {
fs.getSavedFileList({
success(res) {
res = res.fileList;
let size = 0;
for (let index = 0; index < res.length; index++) {
size += res[index].size;
}
size = size / 1048576; //字节转成 MB
console.log(size);
if (size > 170) {
delimgstor(res, data).then((res)=>{
resolve(res);
})
} else {
let data2 = data.filter((item) => {
return item.imgurl
})
downloadImg(data2).then((res => { //去下载
resolve(res);
}))
}
}
})
})
}

// 删除前四分之一
function delimgstor(res, data) {
let bimgStor = wx.getStorageSync('imgStor') || [];
let num = Math.floor(bimgStor.length / 4);
let promiseList = []
return new Promise((resolve, reject) => {
for(let i = 0; i < num; i++){
for(let j = 0;j<bimgStor[i].data.length;j++){
promiseList.push(new Promise((resol, reje) => {
fs.removeSavedFile({
filePath: bimgStor[i].data[j].ImgSave,
success(res) {
resol(i)
console.log(res, 'rrrr')
},
fail(res) {
console.log(res, 'eeee')
resol(i)
}
})
}))
}
}
Promise.all(promiseList).then((res) => {
let delarr = unique(res);
let cimgStor = wx.getStorageSync('imgStor') || [];
for(let i=0;i<delarr.length;i++){
cimgStor.splice(i,1)
}
wx.setStorageSync("imgStor", cimgStor);
downloadImg(data).then((ress => {
resolve(ress);
}))
})
})
}
function unique (arr) {
return Array.from(new Set(arr))
}
// 下载图片
async function downloadImg(data) {
let arr = [];
let data2 = data.filter((item)=>{
return item.imgurl
})
for (let i = 0; i < data2.length; i++) {
let imgs = await downloadImg2(data2[i]);
arr.push(imgs)
}
console.log("下载全部执行完毕了~!~~~~~!!!!!!");
return arr  
}

function downloadImg2(item){
var p = new Promise(function (resolve, reject) {
console.log("我要开始下载了");
wx.downloadFile({
url: item.imgurl+'?size=s',
success: function (res) {
if (res.statusCode === 200) {
fs.saveFile({
tempFilePath: res.tempFilePath,
success(r) {
let obj = {
detectId: item.detectId,
imgurl: item.imgurl,
ImgSave:r.savedFilePath
}
resolve(obj)
}
})
}
}
})
})
return p
}

module.exports = {
chekcimgstorsize
}

然后在需要调用的地方

 getImgData() {
util.get(api.xxx, { }).then(async (res)=>{
try{
truck1 = await upImg.chekcimgstorsize(this.data.warrantyId, truck1);
}
catch{
console.log("缓存的方法报错了~");
}
}))

整体思路是,根据详情页的 id 去 localstorage 里找,如果没有,则直接返回网络路径,同时下载,下载完成后存在本地(最大只能存 200M,如果到 170 则删除最前面的四分之一)。这里的下载是文件,和 localstorage 是两个东西,localstorage 存的是 id 和数据。如果找到了则返回本地存的路径。如果出错了也要处理一下。

<image src="{{item.imgurl}}" wx:if="{{item.isSave == 1 }}" binderror="imgErrorss" class="up_smimg" mode="aspectFit" data-img="{{item.imgurl2}}" data-index="{{index}}"></image>
<image src="{{item.imgurl}}?size=s" wx:else class="up_smimg" data-img="{{item.imgurl2}}" data-index="{{index}}" mode="aspectFit"></image>
imgErrorss(e){
let truck1 = this.data.truck1;
truck1[e.currentTarget.dataset.index].imgurl= e.currentTarget.dataset.img
this.setData({ truck1 })
},

大概这样。还没经过我们组的一个专业测试进行测过,可能会有 bug。