
選擇本地相冊圖檔或者拍照,然後預覽并且上傳是移動應用中一個典型的使用場景,比如常見的身份證資訊上傳等。
不少客戶都回報有類似的場景,并且在使用上都或多或少的遇到一些問題,最後找到 mPaaS,希望我們能夠提供一些最佳實踐。在這裡分享下對應場景的一些優化解決方案。
選圖方案
方案1:使用 Android 原生 Webview
前端通過 input 标簽,指定 type=file,通過原生 webview 的支援實作選擇檔案。
Android 原生 webView 并不支援選擇檔案上傳,需要外殼自己擴充 WebChromeClient 裡的 openFileChooser 或者 onShowFileChooser,然後去喚起系統選擇檔案彈框,選擇檔案會使用系統提供的元件或者其他支援的 app,傳回的 uri 有的直接是檔案的 url,有的是 contentprovider 的 uri,需要統一處理一下傳回 uri 格式。
這種方案存在以下問題:
- 外殼定制實作的邏輯較多,還需要對系統不同檔案選擇器傳回的位址做相容,容易有相容性問題;
- 選擇檔案實作依賴系統的檔案選擇器,不同手機實作不一緻,無法做到統一;
方案2:使用 mPaas 的 H5 容器
如果業務使用了 mPaas 的 H5 容器後,雖然容器内已經内置了喚起檔案選擇器的一系列操作,但是還是一樣存在系統檔案選擇器不可控的風險。比如如果業務希望選擇的是一張圖檔,但是喚起後的效果可能是下面這個樣子,部分客戶也是無法接受的。
方案3:實作 jsapi 喚起 Native 自定義的選圖頁面
這種方案就是利用 H5 容器提供的自定義 jsapi 的能力,自定義一個選圖的 jsapi,然後前端去調用,去喚起 Native 自己實作的選圖頁面,最後結果通過 base64 的形式傳回給前端做顯示。這樣就解決了前面提到系統選擇檔案不可控的問題。
但是當這個方案上線後,還是遇到了一些問題,主要因為通過 jsbridge 隻能傳回 json,是以圖檔資料是通過 base64 的形式傳回的。但是因為有多選的場景,如果使用者選擇了多張圖檔後,傳回的 base64 資料會特别大,導緻在一些低端裝置上有一些 OOM 的問題,同時大量 base64 轉 JSON 的過程中,也會出現 ANR。是以也是不能上線的。
方案4:選圖傳回本地路徑,WebView 攔截通路本地資源
為了解決前面提到的傳回 base64 存在的穩定性問題,是以我們在選圖的時候,是傳回了一個本地的位址,然後 Native 子產品攔截 WebView 的資源通路,去本地拿到對應的圖檔傳回給 WebView 顯示。
比如選圖後傳回給 WebView 的位址是:
https://www.mPaas.com.cn/mpaas.jpg,www.mPaas.com.cn是我們自定義的一個域名,我們攔截這個特定自定義域名,然後去本地相冊去找 mpaas.jpg對應的圖檔攔截傳回。通過這樣的一個轉換邏輯,解決了 base64 傳遞的問題。
檔案上傳方案
通過以上的描述,我們對比了各種選圖方案實作的優缺點,最後沉澱了最佳實踐。選圖實作了後,下一步就是上傳。對于上傳也經曆了類似的方案演進。
方案1:使用 RPC 接口上傳
對于使用了 mPaas 的使用者,第一步想到的肯定是通過 RPC 接口實作檔案的上傳,但是在實際驗證過程中,我們發現對于一些比較大的圖檔上傳,RPC 接口直接傳回了 403 的報錯:Http Transport error[413] : Request Entity Too Large]. 很明顯是因為檔案過大導緻服務端挂掉了。
主要因為 RPC 的定位是用做業務資料通道,一般建議的大小是 200K 以内,對于直接上傳大檔案的資料,會有穩定性風險,甚至因為這個把整個網關打挂。
方案2:使用 OSS 方案上傳
對于類似的檔案上傳場景,建議是直接使用 OSS 的方案進行上傳,比如常見的阿裡雲 OSS 方案:help.aliyun.com/product/31815.html。
OSS 是專門為解決檔案存儲整條鍊路設計的一套方案,解決了檔案上傳的各種場景,使用者可以內建對應的 Android 和 iOS 的 SDK 實作對本地檔案的上傳。
結語
僅僅是一個選圖上傳預覽這樣一個場景,就可以有這麼多不同的方案演進,沒有最好的方案,隻有最合适的方案。如有更多技術問題,歡迎釘釘搜尋“32930171”加入 mPaaS 技術交流群。
- END -