一、问题场景
利用uniapp开发app的项目中,遇到需要频繁访问的资源,如图片或者其他静态文件时,为了降低服务器的网络请求和节省网络
宽带成本,可以通过本地缓存的方式
二、实现技术
主要利用uni.downloadFile 和 uni.saveFile:这是 uni-app 提供的文件下载和文件保存 API。uni.downloadFile 用于从远
程服务器下载文件到临时文件路径,而 uni.saveFile 则用于将临时文件保存到本地永久存储路径。然后将路径通过uni.setStorageSync
缓存到本地,当再次调用的时候通过uni.getStorageSync来判断是否已经存在这个资源地址
三、资源缓存的好处与坏处
好处:
1. 减少网络请求: 通过在本地缓存中存储资源,可以减少对服务器的请求,从而提高应用程序的性能并节省网络带宽。
2. 提高加载速度: 使用本地缓存可以显著提高页面或应用的加载速度,因为本地资源的加载速度通常比网络请求快得多。
3. 离线访问: 通过在本地缓存中存储资源,可以实现离线访问功能,使用户在没有网络连接的情况下仍然能够访问应用程序的某些部分。
4. 减少服务器负载: 由于本地缓存可以减少对服务器的请求,因此可以降低服务器的负载,使其更容易处理其他请求。
坏处:
1. 占用本地存储空间: 如果缓存的资源较多或较大,可能会占用用户设备的存储空间,尤其是在移动设备上可能会受到限制。
2. 更新管理: 当服务器端的资源发生变化时,需要考虑如何更新本地缓存,以确保用户获得最新版本的资源,这可能需要一些额外的逻辑和管理。
3. 缓存一致性问题: 当资源更新时,可能会出现本地缓存和服务器端资源不一致的情况,需要谨慎处理以避免这种情况。
4. 安全性问题: 将资源存储在本地可能会引发一些安全性问题,特别是对于敏感数据或敏感操作的应用程序,需要谨慎处理缓存的内容。
四、实现方案
1.index.vue
<template>
<view>
<hc-image :url='imgUrl' :fileMd5="imgMd5" width="100rpx" height="100rpx"></hc-image>
</view>
</template>
<script>
import hcImage from '@/components/hcImage.vue'
export default {
components:{
hcImage
},
data() {
return {
imgUrl:'',
imgMd5:''
}
},
onLoad() {
},
methods: {
}
}
</script>
<style>
</style>
imageApi.js
export default {
install(Vue) {
Vue.prototype.$getAndCacheImage = function(url, fileMd5) {
const localFileName = 'IMAGE_CACHE_INFO_' + fileMd5.split('/').pop(); // 从URL中提取文件名作为本地文件名
// 构造本地存储路径
const localFilePath = uni.getStorageSync(localFileName)
return new Promise((resolve, reject) => {
// 检查本地是否存在缓存文件
if (localFilePath) {
console.log('已经缓存为', localFilePath)
resolve(localFilePath)
} else {
uni.downloadFile({
url: url,
success(downloadRes) {
if (downloadRes.statusCode === 200) {
// 下载成功,保存文件到本地
const tempFilePath = downloadRes.tempFilePath;
// 保存文件到本地
uni.saveFile({
tempFilePath: tempFilePath,
success(saveRes) {
// 保存成功,返回本地路径
console.log("保存成功:", saveRes.savedFilePath);
uni.setStorageSync(localFileName, saveRes.savedFilePath)
resolve(saveRes.savedFilePath);
},
fail(saveErr) {
console.error("保存失败:", saveErr);
reject(saveErr);
}
});
} else {
console.error("下载失败:", downloadRes);
reject(new Error('Failed to download image'));
}
},
fail(downloadErr) {
console.error("下载失败:", downloadErr);
reject(downloadErr);
}
});
}
});
};
}
};
组件hcImage.vue
<template>
<view>
<image :src="src" :style="{width:width,height:height}" mode=""></image>
</view>
</template>
<script>
export default {
props:{
url:{
type:String,
default(){
return ''
}
},
fileMd5:{
type:String,
default(){
return ''
}
},
width:{
type:String,
default(){
return ''
}
},
height:{
type:String,
default(){
return ''
}
}
},
data() {
return {
src:'',//图片地址
}
},
watch:{
//监听MD5变化
fileMd5(val){
this.getAndCacheImageApi()
}
},
created() {
//查看获取图片缓存
this.getAndCacheImageApi()
},
methods: {
getAndCacheImageApi(){
let that = this
this.$getAndCacheImage(this.url,this.fileMd5)
.then(localFilePath => {
// 使用本地缓存的图片
if(localFilePath){
that.src = localFilePath
}else{
that.src = that.url
}
})
.catch(error => {
// 处理错误
console.error('Error:', error);
});
}
}
}
</script>
<style>
</style>
全局函数
main.js
import Vue from 'vue'
import ApiUtils from './utils/imageApi.js'
Vue.use(ApiUtils)