用web-view?+?H5一招搞定微信小程序選不了本地文件
前言:小程序文件選擇的尷尬
在微信小程序里做「上傳文件」功能時(shí),很多人會(huì)第一時(shí)間想到 wx.chooseMessageFile。用了一段時(shí)間才發(fā)現(xiàn):它只能從聊天記錄里選文件,根本不會(huì)調(diào)起系統(tǒng)文件管理器。
這就導(dǎo)致:
- 用戶:沒法從 iCloud Drive、本地文件夾、最近下載里選文件,只能先把文件發(fā)到某個(gè)聊天再選,體驗(yàn)很割裂
- 產(chǎn)品訴求:希望支持「從手機(jī)文件導(dǎo)入」,和「從聊天導(dǎo)入」并存
- 平臺(tái)限制:小程序沒有提供「調(diào)起系統(tǒng)文件選擇器」的 API,只能另辟蹊徑
所以我們的目標(biāo)很明確:在不大改現(xiàn)有邏輯的前提下,增加一種「從手機(jī)本地文件導(dǎo)入」的方式。最后采用的方案是:用 <web-view> 打開一個(gè) H5 頁面,在 H5 里用 <input type="file"> 調(diào)起系統(tǒng)文件選擇器,選完上傳后再通知小程序刷新列表。
下面就是這條路上的踩坑和實(shí)現(xiàn)要點(diǎn),給有類似需求的同學(xué)做個(gè)參考。
踩坑經(jīng)歷
坑一:以為 postMessage 能實(shí)時(shí)通知小程序
H5 里上傳成功后,很自然就想用 wx.miniProgram.postMessage({ success: true }) 告訴小程序「上傳好了,去刷新列表吧」。
結(jié)果發(fā)現(xiàn):postMessage 并不是實(shí)時(shí)送達(dá)的。消息只會(huì)在 web-view 的特定時(shí)機(jī)(例如用戶點(diǎn)擊返回、分享、頁面被銷毀)才被小程序收到,不能指望「上傳接口返回 200 就立刻讓列表刷新」。
所以更穩(wěn)妥的做法是:上傳成功后直接 wx.miniProgram.navigateBack() 回到列表頁,在列表頁的 onShow 里統(tǒng)一做一次刷新。這樣不依賴 postMessage 的時(shí)機(jī),邏輯也更簡(jiǎn)單。
坑二:業(yè)務(wù)域名和服務(wù)器域名搞混
在微信里,業(yè)務(wù)域名和服務(wù)器域名是兩套配置:
- 業(yè)務(wù)域名:
<web-view>的src必須是已配置的業(yè)務(wù)域名下的頁面,否則體驗(yàn)版/正式版里 web-view 會(huì)白屏或報(bào)錯(cuò) - 服務(wù)器域名:request、uploadFile 等接口要請(qǐng)求的 API 域名,在「服務(wù)器域名」里配置
我們一開始只在「服務(wù)器域名」里配了 API 的域名,結(jié)果 web-view 加載的 H5 地址沒進(jìn)「業(yè)務(wù)域名」,真機(jī)上就打不開。記得把 H5 頁面的域名(例如 https://your-h5.com)配到「開發(fā)管理 → 開發(fā)設(shè)置 → 業(yè)務(wù)域名」,并且域名根路徑要放好微信的校驗(yàn)文件。
坑三:H5 頁面和 API 的域名沒分開配
H5 頁面可能部署在前端靜態(tài)資源域名,上傳接口在后端 API 域名,兩者不一定同域。如果只在 H5 里寫死一個(gè) baseURL,以后換環(huán)境、換域名就要改代碼。
我們的做法是:小程序跳轉(zhuǎn) web-view 時(shí),把當(dāng)前環(huán)境的 API 根地址通過 URL 參數(shù)(如 api_base)傳給 H5,H5 用這個(gè)參數(shù)拼上傳接口的完整 URL。這樣小程序側(cè)用 getEnvBaseUrl() 之類的方法根據(jù)環(huán)境變量取 API 地址即可,H5 只認(rèn)參數(shù),方便多環(huán)境部署。
坑四:web-view 里該用獨(dú)立 HTML 還是 Vue 頁面
web-view 里跑的是完整瀏覽器環(huán)境,理論上可以塞進(jìn)去一個(gè) Vue 應(yīng)用。但考慮到:
- 這個(gè)頁面只有一個(gè)「選文件 → 上傳」的簡(jiǎn)單流程
- 希望加載盡量快、不依賴一堆 JS 庫
- 部署要簡(jiǎn)單,最好和主站一起發(fā)版即可
我們最終選的是:在 public/h5/ 下放一個(gè)獨(dú)立的 upload-file.html,不經(jīng)過 Vue 打包,只引微信 JS-SDK,用原生 JS 做選文件和 XHR 上傳。這樣無需額外構(gòu)建、體積小、首屏快,也避免和主項(xiàng)目路由、構(gòu)建環(huán)境耦合。
坑五:token 怎么安全地給到 H5
H5 調(diào)用后端上傳接口需要帶鑒權(quán)(如 Authorization: Bearer <token>)。token 在小程序里已有,但 H5 拿不到小程序的 storage。
我們采用的方式是:小程序打開 web-view 時(shí),把 token 放在 URL 的 query 里(例如 ?token=xxx&user_id=xxx&api_base=xxx)。
風(fēng)險(xiǎn)控制方式:僅用于這一次上傳流程、token 有時(shí)效、全程 HTTPS。如果你們對(duì) token 暴露在 URL 里特別敏感,也可以讓后端為「web-view 上傳」單獨(dú)發(fā)一次性臨時(shí) token,用一次即廢。
方案架構(gòu)與數(shù)據(jù)流
整體可以理解為三塊:小程序列表頁 → web-view 容器頁 → H5 上傳頁,再加大后端上傳接口。
- 小程序列表頁:列表 + 添加文件入口;點(diǎn)擊「從手機(jī)文件導(dǎo)入」時(shí)跳轉(zhuǎn)到 web-view 頁面,并帶上 token、user_id、api_base 等參數(shù)(通過 web-view 的 URL 傳)。
- web-view 頁面:只負(fù)責(zé)承載一個(gè)全屏 web-view,
src指向 H5 上傳頁的完整 URL(含上述參數(shù))。 - H5 上傳頁:一個(gè)獨(dú)立 HTML,內(nèi)有一個(gè)「選擇文件」按鈕(對(duì)應(yīng)
<input type="file">),選完做前端校驗(yàn)(大小、格式),再用 XHR 以multipart/form-data調(diào)后端上傳接口,成功后調(diào)用wx.miniProgram.navigateBack()回到小程序。 - 列表頁 onShow:從 web-view 返回時(shí)會(huì)再次觸發(fā)
onShow,在這里調(diào)refreshList()拉最新列表即可,無需依賴 postMessage。
這樣用戶路徑就是:添加文件 → 選擇「從手機(jī)文件導(dǎo)入」→ 進(jìn)入 H5 → 選文件 → 上傳 → 自動(dòng)返回 → 列表已更新。
關(guān)鍵實(shí)現(xiàn)要點(diǎn)
1. 小程序側(cè):導(dǎo)入方式用 ActionSheet 二選一
在「添加文件」處不直接調(diào) wx.chooseMessageFile,而是先彈出 ActionSheet,再根據(jù)用戶選擇走不同分支:
- 從聊天中導(dǎo)入:走原來的
wx.chooseMessageFile邏輯 - 從手機(jī)文件導(dǎo)入:
navigateTo到 web-view 頁面,并把 H5 地址和參數(shù)拼好(H5 根地址用getH5BaseUrl()按環(huán)境區(qū)分,再拼上路徑和 query)。
2. H5 頁:input[type=file] + XHR 上傳
- 用
<input type="file" accept=".pdf,.doc,.docx">調(diào)起系統(tǒng)文件選擇器(iOS/Android 都會(huì)用系統(tǒng)原生選擇器)。 - 在
change里取 file,做前端校驗(yàn):大?。ㄈ?≤10MB)、格式白名單。 - 用
FormData把 file 塞進(jìn)去,XHR 的 URL 用 URL 參數(shù)里的api_base拼出完整上傳地址,請(qǐng)求頭里加Authorization: Bearer <token>(token 從 URL 參數(shù)里?。?。 - 上傳成功后調(diào)用
wx.miniProgram.navigateBack(),失敗則在當(dāng)前頁提示錯(cuò)誤,允許重選重傳。
3. 環(huán)境與域名配置
- 為不同環(huán)境(開發(fā)/體驗(yàn)/正式)配置兩套:H5 頁面域名(業(yè)務(wù)域名)、API 域名(服務(wù)器域名)。
- 小程序里用
getH5BaseUrl()、getEnvBaseUrl()之類方法按環(huán)境選 base,再拼到 web-view 的 URL 和api_base參數(shù)里。 - 微信后臺(tái):業(yè)務(wù)域名里配 H5 所在域名;request / uploadFile 合法域名里配后端 API 域名(若 H5 用 XHR 直連后端,則后端域名要在這里配置)。
4. 安全性簡(jiǎn)要說明
- token 通過 HTTPS 的 URL 傳參,僅用于本次上傳,并有時(shí)效。
- 文件類型、大小在前端做一次校驗(yàn),后端再做一次(如只允許 PDF/DOC/DOCX、大小上限 10MB),避免濫傳。
小結(jié)
用 web-view + H5 的 <input type="file"> 來擴(kuò)展「從手機(jī)文件導(dǎo)入」,可以繞過小程序無法調(diào)起系統(tǒng)文件選擇器的限制,同時(shí)保留「從聊天導(dǎo)入」的原有邏輯。實(shí)現(xiàn)時(shí)注意:
- 不依賴 postMessage 觸發(fā)刷新:用
navigateBack+ 列表頁onShow刷新列表更穩(wěn)。 - 業(yè)務(wù)域名:web-view 的 H5 域名必須配在「業(yè)務(wù)域名」里,并放好校驗(yàn)文件。
- H5 與 API 域名分離:通過 URL 參數(shù)把
api_base、token 等傳給 H5,便于多環(huán)境和后續(xù)擴(kuò)展。 - 簡(jiǎn)單場(chǎng)景用獨(dú)立 HTML:上傳頁邏輯簡(jiǎn)單時(shí),獨(dú)立 HTML + 微信 JS-SDK 就夠用,無需上 Vue 全家桶。
- token 傳參:HTTPS + 短期 token 可接受;若有更高安全要求,可改為一次性臨時(shí) token。
如果你也在做小程序里的「從手機(jī)本地選文件」能力,希望這篇能少讓你走一點(diǎn)彎路。
到此這篇關(guān)于用web-view+H5一招搞定微信小程序選不了本地文件的文章就介紹到這了,更多相關(guān)web-view H5微信小程序選本地文件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript實(shí)現(xiàn)獲取瀏覽器版本、操作系統(tǒng)類型
這篇文章主要給大家分享一段javascript實(shí)現(xiàn)獲取瀏覽器版本、操作系統(tǒng)類型的封裝好的代碼,使用非常方便,也很實(shí)用,推薦給大家。2015-01-01
FullCalendar日歷插件應(yīng)用之?dāng)?shù)據(jù)展現(xiàn)(一)
fullcalendar作為一個(gè)功能完善的日歷插件使用非常廣泛,在web開發(fā)開發(fā)過程 中非常流行。它與ext js 中的calendar非常類似,但考慮到extjs 比較“復(fù)雜龐大”,所以我在開發(fā)開發(fā)過程中都會(huì)優(yōu)先考慮fullcalendar2015-12-12
前端必知必會(huì)的實(shí)現(xiàn)URL查詢參數(shù)的方法詳解
URL?參數(shù)查詢是指在?URL?中使用問號(hào)(?)后面附加的鍵值對(duì)參數(shù),本文為大家詳細(xì)介紹了前端實(shí)現(xiàn)URL查詢參數(shù)的方法,希望對(duì)大家有所幫助2025-02-02
js用于樹型結(jié)構(gòu)級(jí)聯(lián)選擇
js用于樹型結(jié)構(gòu)級(jí)聯(lián)選擇...2007-01-01
詳解用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離
本篇文章主要介紹了用函數(shù)式編程對(duì)JavaScript進(jìn)行斷舍離,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09
javascript數(shù)組按屬性分組實(shí)現(xiàn)方法
在開發(fā)過程中,前端有時(shí)需要對(duì)后端返回的數(shù)據(jù)進(jìn)行一些處理,當(dāng)后端返回給我們json對(duì)象數(shù)組時(shí),我們可能會(huì)需要按照對(duì)象中的某一個(gè)屬性來進(jìn)行分組,下面這篇文章主要給大家介紹了關(guān)于javascript數(shù)組按屬性分組的實(shí)現(xiàn)方法,需要的朋友可以參考下2023-05-05
use jscript List Installed Software
use jscript List Installed Software...2007-06-06

