項(xiàng)目場(chǎng)景如下
開(kāi)發(fā)框架是uniapp镊绪,使用uniapp腳手架搭建,最終打包成H5部署在服務(wù)器上。
微信小程序的主體內(nèi)容使用了<web-view>標(biāo)簽將H5的頁(yè)面內(nèi)容展示,H5中有頁(yè)面存放了下載的路徑泉粉。點(diǎn)擊下載按鈕下載文件,或者預(yù)覽文件讓用戶手動(dòng)保存榴芳。
難點(diǎn)
如果是pc端嗡靡,下載用一個(gè)<a>標(biāo)簽就很容易,但是在小程序里的<web-view>標(biāo)簽中是行不通的窟感。此外讨彼,小程序里的<web-view>與小程序的通行方式主要用postMessage,但是觸發(fā)條件非呈疗恚苛刻,參照微信的官方文檔哈误,只在小程序后退,組件銷毀躏嚎,還有分享時(shí)才會(huì)觸發(fā)postMessage并一次性把值全部帶出來(lái)蜜自,使用起來(lái)非常不變,對(duì)于小程序?qū)嶋H內(nèi)容主體是<web-view>內(nèi)嵌的spa的H5頁(yè)面的情況下卢佣,銷毀組件會(huì)帶來(lái)很多麻煩重荠,因此最后放棄了這個(gè)方案。
我的方法
首先必不可少的是安裝jweixin-module模塊
npm i jweixin-module
在main.js中將依賴綁定
import wx from "jweixin-module"
Vue.prototype.$wx = wx
H5對(duì)應(yīng)頁(yè)面點(diǎn)擊下載時(shí)
假設(shè)你的文件路徑是
https://sample.com/apiName.do?fileToken=ABCDEFG&fileName=HIJKLMN.png
這里有需要注意的3點(diǎn)
1是虚茶?會(huì)被微信小程序解析戈鲁,所以需要替換成&,等傳入微信再去拼接
2是fileName與fileToken嘹叫,假設(shè)鏈接里有這些額外的參數(shù)荞彼,那這些參數(shù)因?yàn)楹芸赡芙M成內(nèi)容比較復(fù)雜,會(huì)有特殊字符待笑,所以需要轉(zhuǎn)義鸣皂,然后在微信小程序的看情況有需要的話就解析回去。這里使用encodeURIComponent與decodeURIComponent去處理可能存在特殊字符的字段暮蹂。
3是我的實(shí)際場(chǎng)景里寞缝,獲取服務(wù)器的圖片需要鑒權(quán),所以我會(huì)額外帶一個(gè)cookie仰泻,也使用&拼接在鏈接后荆陆。
let fileToken = "ABCDEFG"
let fileName = "HIJKLMN.png"
this.$wx.miniProgram.navigateTo({
url:"/pages/upload/page?link=https://sample.com/apiName.do&fileToken="+encodeURIComponent(fileToken) + "&fileName=" + encodeURIComponent(fileName)
})
小程序里,對(duì)應(yīng)的/pages/upload/page頁(yè)面
onLoad: function(options) {
let that = this;
wx.setStorageSync('uploadData', options)//保存?zhèn)魅氲膮?shù)
//option為一個(gè)對(duì)象集侯,內(nèi)容就是{ link,fileToken,fileName,cookie等之前使用&拼上的數(shù)據(jù)}
let pages = getCurrentPages();
let previousPage = pages[pages.length - 2]; //上一個(gè)頁(yè)面
previousPage.setData({
isDownLoadPageBack: true //在上一個(gè)頁(yè)面設(shè)置標(biāo)記被啼,用來(lái)判斷
})
wx.navigateBack({
delta: 1
})
},
返回到之前有web-view 的頁(yè)面
data: {
isDownLoadPageBack: false,
},
onShow: function() {
wx.hideHomeButton();
if (this.data.isDownLoadPageBack) {
this.getDownLoadFile() //具體的微信下載文件的方法
}
//每次onShow執(zhí)行完帜消,還有上面的下載方法執(zhí)行完后要把這個(gè)標(biāo)記重置為false,這樣不同情況觸發(fā)的onShow才能區(qū)分是否是下載文件頁(yè)面回來(lái)的浓体∨萃Γ可能寫(xiě)的重復(fù)但是多寫(xiě)幾次比較放心
this.setData({
isDownLoadPageBack: false
})
},
下載方法
getDownLoadFile: function() {
wx.showLoading({
title: '下載中', //提示文字
mask: true, //是否顯示透明蒙層,防止觸摸穿透命浴,默認(rèn):false
})
let that = this;
let options = wx.getStorageSync('uploadData')
let timeStamp = (Date.parse(new Date())) / 1000; //定義了時(shí)間戳拼接在文件名前防止名字重復(fù)
//這里是判斷文件類型娄猫,是否是圖片,后面用來(lái)判斷并使用不同的展示方式
//寫(xiě)的很菜生闲,湊合看下就行
let originFileName = decodeURIComponent(options.fileName)
let originFileNameSplit = originFileName.split('.')
let fileNameType = originFileNameSplit[originFileNameSplit.length - 1]
let imageType = ['gif', 'png', 'jpg', 'tif', 'bmp', 'webp', 'jpeg', 'JPG', ]
let myCookie = decodeURIComponent(options.cookie)
const downloadTask = wx.downloadFile({ //微信下載文件方法
//這里拼接成需要的格式
url: options.link + '?fileToken=' + options.fileToken + '&&fileName=' + options.fileName,
header: {
'cookie': myCookie
},
success(res) {
wx.getFileSystemManager().saveFile({ //微信保存文件媳溺,這個(gè)存儲(chǔ)有點(diǎn)復(fù)雜
// 臨時(shí)存儲(chǔ)路徑,先有臨時(shí)存儲(chǔ)路徑方可使用wx官方的存儲(chǔ)本地路徑( wx.env.USER_DATA_PATH )
tempFilePath: res.tempFilePath,
//定義本地的存儲(chǔ)路徑及名稱
filePath: wx.env.USER_DATA_PATH + '/' + timeStamp + originFileName,
success(res) {
const savedFilePath = res.savedFilePath;
wx.hideLoading()
if (imageType.includes(fileNameType)) {
wx.previewImage({
urls: [savedFilePath],
})
} else {
wx.openDocument({ //微信打開(kāi)文件
filePath: savedFilePath,
showMenu: true,
success: function(res) {
that.setData({
waitWord: '返回請(qǐng)點(diǎn)擊左上角',
isDownLoadPageBack: false
});
},
fail: function(err) {
console.log(res)
wx.showToast({
title: '預(yù)覽失敗',
icon: 'error',
duration: 1500
})
that.setData({
waitWord: '文件預(yù)覽失敗,請(qǐng)稍后重試',
isDownLoadPageBack: false
});
}
});
}
},
fail(err) {
wx.showToast({
title: '預(yù)覽失敗',
icon: 'error',
duration: 1500
})
that.setData({
waitWord: '文件預(yù)覽失敗,請(qǐng)稍后重試',
isDownLoadPageBack: false
});
}
})
},
fail(err) {
wx.hideLoading()
wx.showToast({
title: '下載失敗',
icon: 'error',
duration: 1500
})
console.log(err)
that.setData({
waitWord: '文件下載失敗,請(qǐng)稍后重試',
isDownLoadPageBack: false
});
}
})
downloadTask.onProgressUpdate((res) => {
console.log('下載進(jìn)度', res.progress)
console.log('已經(jīng)下載的數(shù)據(jù)長(zhǎng)度', res.totalBytesWritten)
console.log('預(yù)期需要下載的數(shù)據(jù)總長(zhǎng)度', res.totalBytesExpectedToWrite)
})
}
總結(jié)
大致過(guò)程就這樣碍讯。缺點(diǎn)是點(diǎn)擊下載時(shí)頁(yè)面會(huì)一閃而過(guò)空白的微信頁(yè)面再回來(lái)悬蔽。如果有其他的更友好的實(shí)現(xiàn)方式也請(qǐng)不吝賜教。