在 uni-app 中實現選擇和上傳非圖像、視頻文件,可根據不同端(App、H5、小程序)的特點,采用以下方法:
一、通用思路(多端適配優先推薦)
借助 uni.chooseFile
選擇文件,再用 uni.uploadFile
上傳,不過部分端有差異,需針對性處理:
1. 選擇文件(uni.chooseFile
)
uni.chooseFile({count: 1, // 可選擇文件數量,按需調整type: 'file', // 選擇任意類型文件,若想限制類型,可結合 extension 篩選success: (res) => {const tempFilePath = res.tempFiles[0].path; // 獲取選中文件的臨時路徑// 后續可執行上傳等操作},fail: (err) => {console.error('選擇文件失敗:', err);}
});
- 參數說明:
count
:控制最多選幾個文件,按需設值。type
:設為'file'
可選擇非媒體文件;若想限定特定類型(如文檔),可搭配extension
(H5 端支持 ),例extension: ['.pdf', '.docx']
,不過 App 和小程序端對extension
支持度欠佳,復雜類型篩選可結合后續服務端校驗。- 選中后,
res.tempFiles
里存文件信息,含臨時路徑path
、文件名name
、大小size
等 。
2. 上傳文件(uni.uploadFile
)
拿到選擇的文件臨時路徑后,用 uni.uploadFile
上傳到服務器:
uni.uploadFile({url: 'https://your-server.com/upload', // 實際的服務端文件上傳接口filePaths: [tempFilePath], // 前面選擇文件得到的臨時路徑name: 'file', // 與服務端約定的接收文件的字段名formData: {// 可附帶其他業務參數,如用戶 ID、文件分類等userId: '123',category: 'document'},success: (uploadRes) => {const data = JSON.parse(uploadRes.data);console.log('上傳成功,服務端返回:', data);// 可依據服務端返回做后續處理,如更新文件列表、提示用戶等},fail: (err) => {console.error('上傳失敗:', err);}
});
- 注意事項:
url
要替換成真實的服務端上傳接口地址,需服務端配合實現文件接收邏輯(如 Node.js + Express 用multer
中間件、Java 用 Spring Boot 的文件上傳解析等 )。name
字段要和服務端接口約定一致,否則服務端無法正確識別文件。- 若需更靈活的請求頭設置、進度監聽等,可結合
uni.request
自己構建上傳邏輯(把文件轉成二進制流等方式 ),不過uni.uploadFile
已封裝常見場景,優先推薦。
二、App 端特殊處理(解決兼容性問題)
若 uni.chooseFile
在 App 端選非媒體文件有兼容性問題(如部分安卓機型選特定文件失敗 ),可借助 5+App 的 plus.io.chooseFile
實現:
1. 選擇文件(plus.io.chooseFile
)
// 僅 App 端有效,需判斷平臺后使用
if (uni.getSystemInfoSync().platform === 'android' || uni.getSystemInfoSync().platform === 'ios') {plus.io.chooseFile({title: '選擇文件', // 選擇文件的標題提示filter: '*', // 篩選文件類型,* 表示所有,也可設 '.pdf,.docx' 等multiple: false // 是否多選},(res) => {const fileInfo = res.files[0]; // 獲取選中的文件信息const localPath = fileInfo.path; // 文件本地路徑// 可通過 plus.io 進一步操作文件,如讀取內容、轉成可上傳的格式// 示例:轉成臨時文件路徑,用于 uni.uploadFileconst tempFilePath = plus.io.convertLocalFileSystemURL(localPath); // 執行上傳等操作},(err) => {console.error('選擇文件失敗:', err);});
}
- 優勢:對 App 端文件系統兼容性更好,能處理一些
uni.chooseFile
覆蓋不到的特殊文件選擇場景(如安卓分區存儲下的文件 )。 - 不足:是 5+App 專有 API,H5 和小程序端無法使用,需做平臺判斷,增加代碼復雜度。
2. 上傳文件
拿到文件路徑后,同樣可用 uni.uploadFile
上傳,若遇到文件格式不兼容問題(如服務端需特定二進制流 ),可先用 plus.io
讀取文件內容轉成合適格式再上傳:
plus.io.resolveLocalFileSystemURL(localPath, (entry) => {entry.file((file) => {const fileReader = new plus.io.FileReader();fileReader.onloadend = (e) => {const buffer = e.target.result; // 文件內容的 Buffer 數據// 若服務端需要 FormData 格式,可構造后用 uni.request 上傳const formData = new FormData();formData.append('file', new Blob([buffer]), file.name); uni.request({url: 'https://your-server.com/upload',method: 'POST',header: {'Content-Type': 'multipart/form-data'},data: formData,success: (res) => {console.log('上傳成功:', res.data);}});};fileReader.readAsArrayBuffer(file);});
});
三、H5 端補充(利用瀏覽器特性)
H5 端除了用 uni.chooseFile
,還可直接用 HTML 原生的 <input type="file">
實現更靈活的文件選擇(若 uni.chooseFile
樣式、功能滿足不了需求時 ):
1. 在頁面中添加 input 元素(可通過條件編譯僅在 H5 端顯示 )
<template><view><!-- #ifdef H5 --><input type="file" style="display: none;" ref="fileInput" @change="handleFileChange" /><button @click="openFileSelector">選擇文件</button><!-- #endif --></view>
</template><script>
export default {methods: {openFileSelector() {this.$refs.fileInput.click(); // 觸發文件選擇框},handleFileChange(e) {const file = e.target.files[0]; // 獲取選中的文件const fileReader = new FileReader();fileReader.onload = (event) => {const fileContent = event.target.result; // 文件內容,可轉成 Base64 等// 若要上傳,可構造 FormData 用 uni.request 或 axios 等上傳const formData = new FormData();formData.append('file', file);uni.request({url: 'https://your-server.com/upload',method: 'POST',header: {'Content-Type': 'multipart/form-data'},data: formData,success: (res) => {console.log('上傳成功:', res.data);}});};fileReader.readAsArrayBuffer(file);}}
}
</script>
- 特點:完全基于瀏覽器原生能力,自定義程度高,可靈活控制文件選擇后的處理流程(如讀取文件內容預覽、做加密等 ),但需自己處理多端兼容(僅 H5 端能用 ),且樣式需自己調整。
四、小程序端限制與適配
小程序端 uni.chooseFile
本質是調用各小程序平臺的文件選擇 API,整體流程和前面通用方法一致,但有以下限制:
- 文件類型與大小:不同小程序平臺對可選擇的文件類型、大小有約束(如微信小程序限制單文件最大 100MB 等 ),需在開發時注意。
- 接口能力:
uni.uploadFile
需配置合法域名,且服務端要做相應跨域等配置,否則無法上傳成功。
五、方案推薦與總結
- 優先推薦:用
uni.chooseFile
+uni.uploadFile
的通用方案,多端兼容性較好,能覆蓋大部分場景(如上傳文檔、壓縮包等非媒體文件 ),簡單易實現。 - App 端特殊場景:若通用方案有兼容性問題(如選文件失敗 ),補充
plus.io.chooseFile
的方式,增強對 App 端文件系統的適配。 - H5 端自定義需求:結合原生
<input type="file">
實現更靈活的文件選擇和預處理邏輯。
實際開發中,建議先嘗試通用方案,遇到特定端問題(如 App 端選某些文件報錯、H5 端樣式不滿意 ),再針對性用對應補充方案解決,同時注意服務端配合做好文件接收、校驗邏輯 。