小程序如何解决文件缓存问题?
项目场景:
近期Joe大叔因工作需求,小程序需要实现打开图片文件和PDF功能。当然,被打开的文件是需要增加缓存策略的,要不然每次打开一个6M的PDF文件都去服务端下载然后再打开,会严重影响到小程序迅速响应的用户体验。
问题描述:
那么在实现上述功能时,Joe大叔遇到了一个略显糟心的问题:小程序调用API下载并存储文件到本地后,无法根据本地文件列表确定当前文件是否已下载。
uni.getSavedFileList({success(res) {console.log('获取本地文件列表:\n',res)}
})
// 获取到的数据如下
// {createTime: 1628172373, filePath: "http://store/dleIyVcYMhBP1ec1df7ee3ab6c552f8bd4deff1d1264.jpeg", size: 288419}
原因分析:
现在本地文件列表也拿到了,为什么还不能得知当前文件是否已下载过呢?通过查看数据可以得知,保存好的每一个文件都被封装成了一个字典对象。其中 filePath 表示文件的本地路径,createTime 表示文件保存时的时间戳,size 表示文件的大小。首先把时间戳、文件大小排除,就只剩下文件路径。 但是,这个路径是有种编码格式的,也即它是随机的。下载同一个文件,所生成的本地路径都是不同的。那么,我们该如何解决这个问题呢?
解决方案:
Joe大叔在这里先行献丑了,解决方案分两步:(文末附有Github项目地址)
1、每当文件下载、保存成功后,以文件名为 key,保存文件的路径为 value,包装成字典对象并 push 到一个文件列表数组中。再使用 uni.setStorage 把文件列表数组缓存至本地。
// 没有保存过文件,就开启下载任务uni.showLoading({title:'正在下载...',mask:true})var that = this;uni.downloadFile({url:this.imagePath,success(res) {if (res.statusCode === 200) {var tempFilePath = res.tempFilePath;uni.saveFile({tempFilePath:tempFilePath,success(res) {console.log('文件保存成功')var savedFilePath = res.savedFilePath;// 获取本地文件的文件信息uni.getSavedFileInfo({filePath:savedFilePath,success(res) {that.totalSizeStr = parseInt(res.size / 1024 / 1024) + ''}})getStorage(cachedFileKey).then((cachedArray) => {// 以文件名为key,文件保存的路径为value,组装成一个字典对象保存到数组,再把数组写入本地// 创建一个用于承载字典对象的数组var saveFileArray = [];// 先判断本地有无缓存的文件名、文件路径数组if (!!cachedArray && cachedArray.length > 0) {// 若存在则赋值给saveFileArraysaveFileArray = cachedArray} // 把字典装入数组中saveFileArray.push({fileKey: that.imagePath,filePath: savedFilePath})// 再把数组写入本地setStorage(cachedFileKey,saveFileArray).then(() => {that.isDownload = true;// 直接打开文件uni.previewImage({urls:[savedFilePath]})// 更新一下本地文件列表 fileListuni.getSavedFileList({success(res) {that.fileList = res.fileList}})})})}})}},fail(err) {uni.showToast({title:JSON.stringify(err),icon:'none',duration:1000 * 5})},complete() {uni.hideLoading()}})
当再次打开同一个文件地址时,首先使用 uni.getStorage 获取缓存的文件列表数组,再判断数组中是否已包含与当前文件名一致的 key 值。这就可以解决下载的文件无法标记的问题。
// 先判断 fileList 是否为空,为空直接开启文件下载if (this.fileList.length === 0) {// 开启文件下载this.downloadFile()return;}// 再判断是否文件已经下载过getStorage(cachedFileKey).then((cachedArray) => {// 同样要判断 cachedArray 是否存在if (!!cachedArray && cachedArray.length > 0) {// 若存在则进行文件名与 fileKey 的比对var fileKeyArray = [];var fileKeyFilePathArray = [];var resultArray = [];cachedArray.map((item) => {fileKeyArray.push(item.fileKey)fileKeyFilePathArray.push(item)})// 这里使用 filter 函数是一个筛选小技巧,可以直接遍历得到需要的数据resultArray = fileKeyFilePathArray.filter((item) => {if (item.fileKey === this.imagePath) {return true} else {return false}})// 使用数组的 indexOf 方法来比对当前文件名if (fileKeyArray.indexOf(this.imagePath) > -1) {// > -1 表示比对成功,文件已下载,直接打开// 这里需要注意一下:如果是要打开图片,就使用 uni.previewImage// 如果要打开doc, xls, ppt, pdf, docx, xlsx, pptx,就使用 uni.openDocument// 因为我在这里使用的是jpg图片,所以就使用 uni.previewImageuni.showModal({title:'检测到您已下载过此文件,是否直接打开?',success(res) {if (res.confirm) {uni.previewImage({urls:[resultArray[0].filePath],fail(err) {console.log(err)}})}}})} else {// 比对不成功,则直接开启文件下载this.downloadFile()}}})
2、经过Joe大叔实测,小程序文件下载是有上限的,大概100M,本地文件总大小达到或超过这个数之后,就无法下载成功,大家可以亲自试验下。
所以,我们还需要做一个文件缓存策略,怎么做呢?很简单,前面我们已经可以获取到本地缓存文件的大小了,只要遍历出来再进行累加,就能得出总大小。这里要注意一下的是,默认大小是以字节为单位的,所以转换为M的话是需要再除以 1024 * 1024 的。
var that = this;uni.getSavedFileList({success(res) {var fileList = res.fileList;that.fileList = res.fileList;// 判断 fileList 不为空,计算一下文件总大小,如果超限需要删除部分文件以挪出空间if (fileList.length === 0) {return;}var totalSize = 0;// 设置文件缓存限额为50Mvar sizeLimit = 50 * 1024 * 1024;fileList.map((item) => {totalSize += item.size})that.totalSizeStr = parseInt(totalSize / 1024 / 1024) + ''// 判断总大小是否超限if (totalSize >= sizeLimit) {// 执行文件删除操作,具体删除几个文件可以自己调整uni.removeSavedFile({filePath:fileList[0].filePath,success() {}})}}})
Joe大叔对文件总大小设置了50M的限额,当然,大家可以根据实际项目需要进行调整。当总大小超过50M时,需要执行 uni.removeSavedFile 来删除本地保存的文件,以挪出空间。
至此,我们就解决了小程序文件缓存问题,最后再献上对 uni.getStorage、uni.setStorage 的 Promise 封装吧。
/*
这里说下为什么要把 uni.getStorage 和 uni.setStorage 使用 Promise 封装一下:因为封装后用起来爽啊~ uni.getStorage、uni.setStorage 直接使用不适合实际开发,一堆 success、fail 回调
*/ export const getStorage = function(key) {return new Promise((resolve, reject) => {uni.getStorage({key:key,success(res) {resolve(res.data)},fail() {resolve(null)}})})
}export const setStorage = function(key, data) {return new Promise((resolve, reject) => {uni.setStorage({key:key,data:data,success() {resolve(true)},fail() {resolve(false)}})})
}export const cachedFileKey = 'cachedFileKey'
本期Joe大叔有关小程序文件缓存问题的解决方案就在此告一段落了,很感谢能坚持看完这篇文章的朋友们,我们下期再见!
附件:https://github.com/zoeyzhong520/dataDownloadProject
小程序如何解决文件缓存问题?相关推荐
- uniapp 微信小程序开发 解决旧版本缓存
1.uniapp 微信小程序如何解决旧版本缓存问题 在小程序发布新版本后,小程序端是异步更新,新版本覆盖较慢.如果用户之前已经打开过小程序,通过 热启动 再进入小程序时,可能访问的还是旧版本,需要一段 ...
- 微信小程序 本地mysql_微信小程序系列之使用缓存在本地模拟服务器数据库
微信小程序系列之使用缓存在本地模拟服务器数据库 现在将data.js这个文件视作是本地数据库的初始化数据,要做的第一件事就是讲这些初始化数据装进缓存中,以形成数据库的初始化数据 整个应用程序的生命周期 ...
- 小程序性能优化——文件的本地存储10M优化算法
小程序文件的本地存储优化 优化原因! 众所周知,微信将小程序的本地文件存储空间限制为10M,导致我们在调用wx.saveFile()接口存储临时文件时,存着存着,就超过10M了.那该怎么办呢? 肯定是 ...
- 微信小程序如何导入文件的一种方法
微信小程序如何导入文件的一种方法,前三条才是有用的信息 1 环境 2 当你看到好的demo想在自己的小程序试试的时候 3 解决方式,进入本地文件夹直接复制 新的改变 功能快捷键 合理的创建标题,有助于 ...
- 微信小程序上传文件400
微信小程序上传文件400 直接上示例问题代码 将请求头添加上Host即可解决 直接上示例问题代码 wx.uploadFile({url: 'https://' + domain + '/post/up ...
- 微信小程序+SpringBoot实现文件上传与下载
微信小程序+SpringBoot实现文件上传与下载 1.文件上传 1.1 后端部分 1.1.1 引入Apache Commons FIleUpload组件依赖 1.1.2 设置上传文件大小限制 1.1 ...
- 微信小程序下载保存文件
前言 总是有需求想在微信小程序里面做下载文件并保存的功能,所以自己整理了一下小程序涉及到下载api,大致理了下在小程序里面下载的流程和解决方案. 一.涉及api 1.wx.saveFile() 文 ...
- 微信小程序PHP文件建在哪里,微信小程序解析H5文件方法
经常有网友问怎么让微信小程序解析H5文件或者类似封装H5网页到APP里面?我一开始觉得这是不可能的,因为官方的解答是这样的: 每一个小程序页面是由同路径下同名的四个不同后缀文件的组成,如:index. ...
- java实现音频播放小程序_微信小程序实现音频文件播放进度的实例代码
问题描述 在微信小程序中经常会用到控制文件播放的滑块,通过滑块可控制音频播放进度,下面即用代码实现. 解决方案 首先用.wxml与 .wmss 代码实现进度条的效果,再通过 .js 文件控制进度条的进 ...
最新文章
- 数据库事务的四大特性和隔离级别
- LeetCode 264. Ugly Number II--C++,Python解法
- 成都网络推广告诉大家网站抓取量要如何解决?
- 线性代数---线性方程组
- Java核心类库篇6——IO
- hadoop--完全分布式运行模式
- vfp报表纸张设置_VFP 9.0中实现多种自定义纸张格式的报表打印
- IView的Form表单自定义验证需注意事项
- 计算机网络实验题教程推介,计算机网络实验教程从原理到实践(附光盘)
- 2019-08-12 计划与安排
- 寻宝,大冒险!CSP202206-2
- Linux修改http为https访问
- IDM6.39序列号,亲测可用
- HDU - 3966(树链剖分)
- 营销:uplift模型
- 中国石油大学(北京)-《机器人设计》第一阶段在线作业
- Gym101194F-Mr. Panda and Fantastic Beasts
- 计算机替换规定文字颜色,改Windows系统字体颜色的方法
- 微信朋友圈图片显示缩放
- 主从概念以及主从的相关知识