小程式-圖片/文件本地快取,減少CDN流量消耗

寫在前面

小程式網路圖片讀取:

  1. 在讀取OSS圖片CDN分發時流量大量消耗,導致資金費用增加。
  2. 網路圖片比較大時,圖片載入緩慢。

為了盡量減少上面兩個問題,所以對已讀的圖片進行快取處理,減少多次訪問不必要的流量消耗。

小程式的文件系統

文件主要分為兩大類:

  • 程式碼包文件:程式碼包文件指的是在項目目錄中添加的文件。
  • 本地文件:通過調用介面本地產生,或通過網路下載下來,存儲到本地的文件。

其中本地文件又分為三種:

  1. 本地臨時文件:臨時產生,隨時會被回收的文件。不限制存儲大小。
  2. 本地快取文件:小程式通過介面把本地臨時文件快取後產生的文件,不能自定義目錄和文件名。跟本地用戶文件共計,普通小程式最多可存儲 10MB,遊戲類目的小程式最多可存儲 50MB。
  3. 本地用戶文件:小程式通過介面把本地臨時文件快取後產生的文件,允許自定義目錄和文件名。跟本地快取文件共計,普通小程式最多可存儲 10MB,遊戲類目的小程式最多可存儲 50MB。

而我們要使用的文件快取方式就是 本地臨時文件

實現原理

圖片快取流程:

  1. 將要圖片/文件通過wx.downloadFile(Object object)下載到本地,成為本地臨時文件。
  2. 使用小程式的Storage記錄網路地址本地地址,做映射。
  3. 使用時,在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
}

寫在後面

本文參照部落格

  • //juejin.im/post/5b42d3ede51d4519277b6ce3

(幽蟄 寫於 2020.06.10)

Tags: