需求:由於后台服務器各方面的限制,現在服務器返回的圖片是base64格式的,小程序端需要支持預覽圖片和多個圖片一鍵下載功能
一、如何預覽base64位圖片?
WXML頁面:item.src的值是base64編碼的字符串
<block wx:for="{{imgsLength}}" wx:key="index">
<image mode="widthFix" bindtap="preImg" src="data:image/png;base64,{{item.src}}" data-src="{{item.src}}"></image>
</block>
JS: 由於ios13和微信7.0.12匹配有問題,導致預覽圖片的時候使得微信閃退
// 圖片預覽 preImg(e) { let that = this if (that.data.system != '') { let system = that.data.system.substring(0, 3) console.log('system: ', system.toLowerCase()) if (system.toLowerCase() == 'ios') { console.log('當前系統不支持預覽') } else { let url = 'data:image/png;base64,' + e.currentTarget.dataset.src wx.previewImage({ current: url, // 當前顯示圖片的http鏈接 urls: [url] // 需要預覽的圖片http鏈接列表 }) } } },
二、一鍵下載多張base64位的圖片?
需求:(1)由於后台服務器的限制,現只能一張一張請求圖片,且每隔1s請求一次接口,每張圖片總共請求60次。(2)如果圖片請求到則展示圖片,如果請求不到,則在頁面顯示占位圖片,且點擊該圖片需重新發送請求該圖片的接口。
步驟一:頁面加載開始就請求第一張圖片,當第一張圖片返回后或者請求次數已達上限,則請求下一張。
// 請求圖片 getImgsList() { let that = this let token = that.data.scanToken let iData = { currentNumber: that.data.currentPage } var i = 0 let handerRequest = setInterval(function() { // 發送請求 i++; util.request(api.DownloadImgsList, iData, 'POST', token).then(function(res) { if (i === 60) { clearInterval(handerRequest) let number = that.data.currentPage - 1 console.log('失敗圖片是第' + number + '頁') that.setData({ ['imgsLength[' + number + '].requestNum']: i, }) // 查詢下一個 that.getNextImg() } if (res.data.code === 0) { clearInterval(handerRequest) if (!that.data.totalNumber && res.data.data.totalNumber) { console.log('圖片總數----', res.data.data.totalNumber) log.info('圖片總數----', res.data.data.totalNumber) that.setData({ totalNumber: res.data.data.totalNumber, // 圖片總數 }) // 圖片占位數組 let imgsLength = new Array(res.data.data.totalNumber).fill({ 'src': '', 'number': '', 'requestNum': '' }) that.setData({ imgsLength: imgsLength, }) } if (res.data.data.currentNumber && res.data.data.file) { let imgsArr = [] imgsArr.push({ 'src': res.data.data.file, 'number': res.data.data.currentNumber }) that.setData({ imgs: that.reduce(that.data.imgs.concat(imgsArr).sort(that.arraySort('number')), 'number'), }) that.data.imgsLength.find((item, index) => { if ((index + 1) == res.data.data.currentNumber) { let num = index that.setData({ ['imgsLength[' + index + '].src']: res.data.data.file, ['imgsLength[' + index + '].number']: res.data.data.currentNumber, }) } }) } // 查詢下一個 that.getNextImg() } else if (res.data.code === 59706) { console.log('getImgs res: ', res) clearInterval(handerRequest) wx.showToast({ icon: 'none', title: 'token失效,請重新掃碼', }) } else { console.log('請求圖片錯誤', res) } }).catch(err => { if (i === 60) { clearInterval(handerRequest) let number = that.data.currentPage - 1 that.setData({ ['imgsLength[' + number + '].requestNum']: i, }) // 查詢下一個 that.getNextImg() } console.log("請求圖片err:", err); }); }, 1000) }, // 獲取下一個圖片 getNextImg() { let that = this if (that.data.currentPage + 1 <= that.data.totalNumber) { that.setData({ currentPage: that.data.currentPage + 1 }) that.getImgsList() } else { console.log('沒有更多圖片') } },
注意:由於異步可能會使得返回的圖片有重復的或者不是按照請求的順序返回的,因此需要對圖片進行去重和排序
// 圖片去重 reduce(arr, name) { var hash = {} return arr.reduce(function(item, next) { hash[next[name]] ? '' : hash[next[name]] = true && item.push(next); return item; }, []) }, // 圖片排序 arraySort(field) { return function(obj1, obj2) { let a = obj1[field] let b = obj2[field] return a - b } },
如何重新加載之前失敗的圖片:
// 重新加載 loadAgain (e) { let that = this; let number = e.currentTarget.dataset.index // 點擊重新加載當前圖片 let token = that.data.scanToken let iData = { currentNumber: number + 1 } var i = 0 let handerRequest = setInterval(function () { // 發送請求 i++; util.request(api.DownloadImgsList, iData, 'POST', token).then(function (res) { if (i === 60) { clearInterval(handerRequest) } if (res.data.code === 0) { clearInterval(handerRequest) if (res.data.data.currentNumber && res.data.data.file) { let imgsArr = [] imgsArr.push({ 'src': res.data.data.file, 'number': res.data.data.currentNumber }) that.setData({ ['imgsLength[' + number + '].src']: res.data.data.file, ['imgsLength[' + number + '].number']: res.data.data.currentNumber, imgs: that.reduce(that.data.imgs.concat(imgsArr).sort(that.arraySort('number')), 'number'), totalNumber: res.data.data.totalNumber, // 圖片總數 }) } } else if (res.data.code === 59706) { console.log('loadAgain res: ', res) clearInterval(handerRequest) wx.showToast({ icon: 'none', title: 'token失效,請重新掃碼', }) } else { console.log('請求圖片錯誤', res) } }).catch(err => { if (i === 60) { clearInterval(handerRequest) } console.log("請求圖片err:", err); }); }, 1000) },
步驟二:至此,需要下載的圖片已經存進了imgs數組中。由於小程序無法直接將base64的圖片直接保存到本地相冊,因此需要先將文件寫入本地,之后再進行保存到相冊的操作。
1.由於微信小程序限制,小程序文件系統寫入文件,大小最多是10m,在ios上測試的時候發現writeFile報錯,為了規避這個問題,我在寫入文件的時候會先清理之前的文件。 // 下載 download() { let that = this if (that.data.imgs.length > 0 && that.data.imgs.length == that.data.imgsLength.length) { // 先創建一個保存圖片的本地文件目錄 let fs = wx.getFileSystemManager() // 再判斷takeAway目錄是否存在,不存在則新建該目錄 fs.access({ path: `${wx.env.USER_DATA_PATH}/takeAway`, success: res => { console.log('takeAway目錄存在res:', res) log.info('takeAway目錄存在res:', res) that.dow_temp(0) }, fail: err => { console.log('takeAway目錄不存在:', err) log.info('takeAway目錄不存在:', err) fs.mkdir({ dirPath: `${wx.env.USER_DATA_PATH}/takeAway`, success: res => { console.log('創建保存圖片的本地文件路徑成功', res) log.info('創建保存圖片的本地文件路徑成功', res) that.dow_temp(0) }, fail: err => { console.log('創建保存圖片的本地文件路徑失敗', err) log.error('創建保存圖片的本地文件路徑失敗', err) } }) } }) } else { wx.showToast({ icon: 'none', title: '圖片還未完全加載完畢,請稍后再試!', duration: 3000 }) } }, //下載單個內容 dow_temp: function(i, callback) { let that = this var fs = wx.getFileSystemManager() // 先刪除之前takeAway目錄下的文件 return new Promise((resolve) => { fs.readdir({ dirPath: `${wx.env.USER_DATA_PATH}/takeAway`, success(res) { res.files.forEach((el) => { fs.unlink({ filePath: `${wx.env.USER_DATA_PATH}/takeAway/${el}`, fail(e) { console.log('readdir文件刪除失敗:', e) } }) }) resolve(that.saveImgFile(i, callback)) } }) }) },
步驟三:圖片保存
// 圖片保存 saveImgFile: function(i, callback) { let that = this let data = that.data.imgs let all_n = data.length if (i < all_n) { wx.authorize({ scope: 'scope.writePhotosAlbum', success() { var fs = wx.getFileSystemManager(); var number = Math.random(); const downloadTask = fs.writeFile({ filePath: `${wx.env.USER_DATA_PATH}/takeAway/${number}.png`, data: data[i].src, encoding: 'base64', success: res => { wx.saveImageToPhotosAlbum({ filePath: `${wx.env.USER_DATA_PATH}/takeAway/${number}.png`, success: function(res) { wx.showToast({ icon: 'none', title: `第${i + 1}/${all_n}張保存到系統相冊`, }) that.dow_temp(i + 1); }, fail: function(err) { console.info('第', (i + 1), '張保存失敗'); } }) }, fail: err => { wx.showToast({ title: '一鍵保存失敗,請點擊圖片手動保存!', icon: 'none', }) } }) }, fail: function() { wx.showToast({ title: '獲取授權失敗', icon: 'none', }) } }) } },