微信小程序開發技巧總結(二) -- 文件的選取、移動、上傳和下載
文檔更新 EXTEND
1.不同類型文件的選取
1.1 常用的圖片 視頻
對於大部分開發者來說,需要上傳的文件形式主要為圖片,微信為此提供了接口。
wx.chooseImage({
count: 1,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success (res) {
// tempFilePath可以作為img標簽的src屬性顯示圖片
const tempFilePaths = res.tempFilePaths
}
})
其次為視頻文件的選取,微信也為此提供了接口。
wx.chooseVideo({
sourceType: ['album','camera'],
maxDuration: 60, //視頻長度 單位 s
camera: 'back', //選取前置 攝像 還是 后置 攝像
success(res) {
console.log(res.tempFilePath)
}
})
也為其提供了視頻和圖片的二合一接口,這個接口不建議調用,圖片和視頻的上傳建議區分開。
wx.chooseMedia({
count: 9,
mediaType: ['image','video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success(res) {
console.log(res.tempFilePath)con
console.log(res.size)
}
})
這幾個接口調用成功的回調函數中,都返回的是文件在文件在本機中的路徑。
res.tempFilePath
這是一個 數組,存放着選擇的所有文件的路徑,用於上傳。
1.2 其余形式各種文檔
那么如果是想要在小程序中上傳 doc、pdf、ppt 等類型的文件怎么處理?首先要注意的是微信小程序並沒有給用戶提供文件管理器接口。
開發者:我想要個文件管理器接口!
官方:不,你不想
聰明的開發者他沒有辦法,只能另辟蹊徑。微信提供了一個選擇客戶端會話文件的方法。
wx.chooseMessageFile({
success(res){
console.log(res.tempFilePath)
}
})
與上面兩個接口相同,返回的也是文件在本地的存儲路徑,但是不同的是,這個接口可以選取全部的文件類型。
開發者如果想要上傳非圖片和視頻內容的話,需要兩步走。
- 打開微信文件傳輸助手,將想要上傳的文件發送到文件傳輸助手
- 在小程序中調用這個接口,選擇文件傳輸助手,從會話中選擇想要上傳的文件。


2.文件的上傳
2.1 uploadFile方法
所有的文件都是以字節流的形式進行上傳,所以上傳形式並沒有什么本質區別,都是調用相應的接口進行上傳。
小程序端寫法如下:
wx.uploadFile({
url: '你的服務器函數地址', //僅為示例,非真實的接口地址
filePath: '需要上傳的文件路徑', //res.tempFilepaths
name: 'file', // 文件對應的key ,默認 為 file
formData: {
'user': 'test'
}, //上傳額外攜帶的參數
success (res){
const data = res.data
//do something
}
})
2.2 服務器端如何處理上傳的文件
服務端如何接受文件的上傳?僅展示Java方式(SpringBoot 框架)
@Controller
@ResponseBody
public class FileController {
//文件上傳控制類,是核心配置類,Win <->Linux
@RequestMapping(value = "/upload/images")
public String uploadimages(HttpServletRequest request,@RequestParam("file") MultipartFile file, @RequestParam("user") String user) throws IOException {
//更換服務器,這個值也需要修改
//圖片上傳寫法
//type 是上傳圖片的類型
if(!file.isEmpty()){
//文件不為空
//String path = "E:"+File.separator+"images"+File.separator+type; // this is windows method
String path = "/share"+File.separator+"images"+File.separator+type;
// this is Linux method
String filename = file.getOriginalFilename();
File filepath = new File(path,filename);//新建文件存儲路徑
System.out.println(filepath);
if(!filepath.getParentFile().mkdirs()){
filepath.getParentFile().mkdirs();
}
file.transferTo(new File(path+File.separator+filename));
//想要返回可直接訪問的鏈接還要配置 映射,具體請看下面鏈接
return "你的IP地址"+"/images/"+type+"/"+filename;
}else {
return "error";
}
}
}
配置訪問映射
2.3 雲開發文件上傳
微信小程序支持雲開發,其文件上傳接口有一些差異,但是不需要自己再構建后台。
wx.cloud.uploadFile({
cloudPath: 'file/' + '你的文件名字(帶格式后綴)', // 在雲端存儲的路徑
filePath: '', // 就是選擇文件返回的路徑
}).then(res => {
// get resource ID
console.log(res.fileID)
}).catch(error => {
// handle error
})
我們可以根據返回的fileID 置換 真實的文件訪問地址。
其置換方式參見官方文檔:
wx.cloud.getTempFileURL({
fileList: ['cloud://xxx', 'cloud://yyy'],
success: res => {
// get temp file URL
console.log(res.fileList)
},
fail: err => {
// handle error
}
})
TIPS:關於雲開發文件上傳的建議
- 如果沒有保密需求,為了方便后續開發,存儲到數據庫中的最好是可以直接訪問的文件鏈接。
- 置換真實文件地址,不要每次上傳一次文件就置換一次,先把返回的fileID 存放在數組中,到該事務所有上傳完成后,再使用fileID 數組置換真實文件訪問鏈接數組。
- 要考慮文件名重復的可能,建議使用時間戳在 wx.cloud.uploadFile 中的 cloudPath 中對存儲到雲環境中的文件命名進行格式化。
總的來說就是先上傳文件,再向數據庫中寫入記錄。
2.4 多文件同時上傳的處理方式
uploadFile 每次只能上傳一個文件
如何處理這個問題?
A.不考慮文件的上傳次序問題,可以采用遍歷上傳的方式,采用精確的時間戳和遍歷index對文件名進行格式化。通過定時觸發檢測函數判斷是否全部上傳完成。這種方式考慮的是並發能力。
upSeveralfiles() {
wx.showLoading({
title: '上傳中~',
mask: true
})
var that = this;
var timecode = sev.vcode(new Date()); // 這是時間戳編碼函數
var files = this.data.fileList; // 這是 選擇文件中返回的 res.tempFilePath 數組
var len = files.length;
var i = 0;
for (i = 0; i < len; i++) {
var str = files[i].name;
wx.cloud.uploadFile({
cloudPath: 'file/' + '(' + sev.getformatTime(new Date()) + ')' + str,
filePath: files[i].path,
success(res) {
console.log(res)
that.setData({
cloudlist: that.data.cloudlist.concat([res.fileID]),
})
// cloudlist 是存放 文件鏈接置換id 的數組 , 非雲開發存儲的就是真實可訪問的鏈接數組
// 如果使用的不是雲開發 那么 可以返回真實的 訪問地址
},
fail(res) {
console.log(res)
}
})
}
// 使用定時器檢測文件是否全部上傳完成 , 並 判斷是否進行下一步 操作
var timer = setInterval(function () {
if (that.data.cloudlist.length == len) {
// 只有全部上傳成功了 長度才會相等
clearInterval(timer);
// 繼續執行下一步 ,根據 cloudlist 置換真實地址 並存放到數據庫
// 如果使用的非雲開發,那么就繼續執行 存儲至數據庫的操作
}
}, 1000)
}
補充文件編碼函數 sev.js 中的根據時間編碼部分 , 可以根據實際流量自定義。
function getformatTime(date) {
var year = date.getFullYear()
var month = date.getMonth() + 1
var day = date.getDate()
var hour = date.getHours()
var minute = date.getMinutes()
var second = date.getSeconds()
return [year, month, day].map(formatNumber).join('-');
};
B.考慮文件的上傳次序問題,采用回調方式進行文件上傳(更推薦使用這種方式)
data: {
fileList: [],
realList: [],//雲端地址鏈接列表
fileid: 0,
},
upSeveralfiles() {
var that = this;
var files = this.data.fileList; // 這是 選擇文件中返回的 res.tempFilePath 數組
var len = files.length;
var uid = this.data.fileid;
wx.uploadFile({
url: '你的服務器文件接收函數請求地址',
name: 'file',
filePath: files[uid],
header: {
"Content-Type": "multipart/form-data"
},
success(res) {
that.setData({
fileid: uid + 1,
realList: that.data.realList.concat([res.data])
}, () => {
if (that.data.fileid == len) {
// 上傳完成 ,執行下一步操作
} else {
//上傳完一個文件 遞歸執行 下次上傳
that.upSeveralfiles();
}
})
}, fail(res) {
console.log(res.data)
}
})
},
以上是提供的兩種思路 , 無論是不是雲開發 , 兩種思路都是共通的,適用於多文件上傳.
3.文件的下載
這個地方唯一值得注意的是雲開發的一種下載方式 可以通過fileID進行download , 當然只能下載存儲在自己雲環境中的文件.
wx.cloud.downloadFile({
fileID: '',
success: res => {
console.log(res.tempFilePath)
},
fail: err => {
}
})
wx.downloadFile({
url: '', //僅為示例,並非真實的資源
success (res) {
//res.tempFilePath
})
下載進度監控 , 用於下載進度條繪制等功能實現
const downloadTask = wx.cloud.downloadFile({ *** }) // wx.downloadFile 同理
downloadTask.onProgressUpdate((res) => {
//res.progress 為下載進度
})
下載下來的文件支持直接打開,就像是在微信聊天中打開一樣,需要下載插件。
其使用方式為:
wx.openDocument({
filePath: res.tempFilePath //為文件路徑 非數組 , 可使用回調函數 success 等
})
4.文件的移動
這個一般情況下是用不到的, 也不建議使用移動文件的方法作為功能實現手段 ,必然有更好的替代方式,比如修改數據庫路徑 和 真實文件路徑的映射, 效率更高一些.
建議在數據庫中修改映射路徑最好。
需要小程序開發的請聯系我QQ : 1025584691
