提交 706cab6c 作者: 方治民

feat: 优化 CacheImage 组件,记录文件大小及时间戳,以及计算缓存大小和清理功能

上级 a1a5336f
import { convertKB } from '@/utils/file'
/**
* 图片 Hash 缓存标识前缀
*/
export const CACHE_PREFIX = 'G_CACHE_IMAGE__'
/**
* 计算缓存大小
* @returns 字节
*/
export function calculateCacheSize() {
const storage = uni.getStorageInfoSync()
return storage.keys
.filter((key) => key.startsWith(CACHE_PREFIX))
.reduce((total, key) => {
try {
const cache = uni.getStorageSync(key)
const result = JSON.parse(cache)
total += result.size
} catch (_) {}
return total
}, 0)
}
/**
* 计算缓存大小格式化
* @returns 格式化后的缓存大小
* @example 1.2MB
* @see {@link calculateCacheSize}
* @see {@link convertKB}
* @see {@link CACHE_PREFIX}
*/
export function calculateCacheSizeFormat() {
const cacheSize = calculateCacheSize()
const { size, unit } = convertKB(cacheSize)
return `${size}${unit}`
}
/**
* 清理缓存
*/
export function cleanCache() {
const storage = uni.getStorageInfoSync()
const promises = storage.keys
.filter((key) => key.startsWith(CACHE_PREFIX))
.map((key) => {
return new Promise((resolve, reject) => {
try {
const cache = uni.getStorageSync(key)
const result = JSON.parse(cache)
uni.removeSavedFile({
filePath: result.url,
complete: resolve,
})
} catch (e) {
console.error(e)
reject(e)
} finally {
uni.removeStorageSync(key)
}
})
})
return Promise.allSettled(promises)
}
<script setup lang="ts"> <script setup lang="ts">
import md5 from 'crypto-js/md5' import md5 from 'crypto-js/md5'
import { CACHE_PREFIX } from './index'
const props = defineProps({ const props = defineProps({
width: { width: {
...@@ -60,27 +61,53 @@ ...@@ -60,27 +61,53 @@
// 如果是网络图片,则缓存到本地 // 如果是网络图片,则缓存到本地
if (url.startsWith('http')) { if (url.startsWith('http')) {
// #ifdef APP-PLUS // #ifdef APP-PLUS
const hash = md5(url).toString() const hash = md5(url).toString().toUpperCase()
hashCacheKey.value = `G_CACHE_IMAGE_${hash}` hashCacheKey.value = `${CACHE_PREFIX}${hash}`
if (uni.getStorageSync(hashCacheKey.value)) { const cache = uni.getStorageSync(hashCacheKey.value)
if (cache) {
log('cache hit', url) log('cache hit', url)
url = uni.getStorageSync(hashCacheKey.value) try {
const result = JSON.parse(cache)
url = result.url
} catch (_) {
url = cache
}
} else { } else {
log('cache miss', url) log('cache miss', url)
try { try {
const res = await uni.downloadFile({ url }) const res = await uni.downloadFile({ url })
if (res.statusCode === 200) { if (res.statusCode === 200) {
const { savedFilePath } = await new Promise<UniApp.SaveFileSuccess>((resolve, reject) => { const { savedFilePath, size } = await new Promise<{ savedFilePath: string; size: number }>(
uni.saveFile({ (resolve, reject) => {
tempFilePath: res.tempFilePath, uni.saveFile({
success: (res) => resolve(res), tempFilePath: res.tempFilePath,
fail: (err) => reject(err), success: (res) => {
}) const filePath = res.savedFilePath
}) uni.getFileInfo({
filePath,
success: (res) =>
resolve({
savedFilePath: filePath,
size: res.size,
}),
fail: (err) => reject(err),
})
},
fail: (err) => reject(err),
})
},
)
url = `${savedFilePath}` url = `${savedFilePath}`
// 缓存图片本地地址 // 缓存图片本地地址
uni.setStorageSync(hashCacheKey.value, url) uni.setStorageSync(
hashCacheKey.value,
JSON.stringify({
url,
size,
timestamp: Date.now(),
}),
)
} else { } else {
log('cache error', url, res) log('cache error', url, res)
url = props.src url = props.src
...@@ -97,6 +124,7 @@ ...@@ -97,6 +124,7 @@
} }
const hasError = ref(false) const hasError = ref(false)
function onError() { function onError() {
if (hasError.value) { if (hasError.value) {
return return
......
// 将 KB 转换为其他单位
export function convertKB(kb: number) {
const bytes = kb * 1024
const units = ['B', 'KB', 'MB', 'GB', 'TB']
let size = bytes
let unitIndex = 0
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024
unitIndex++
}
return { size: size.toFixed(2), unit: units[unitIndex] }
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论