1.不一樣類型文件的選取javascript
1.1 經常使用的圖片 視頻html
對於大部分開發者來講,須要上傳的文件形式主要爲圖片,微信爲此提供了接口。java
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) } })
這幾個接口調用成功的回調函數中,都返回的是文件在文件在本機中的路徑。windows
res.tempFilePath
這是一個 數組,存放着選擇的全部文件的路徑,用於上傳。微信小程序
1.2 其他形式各類文檔api
那麼若是是想要在小程序中上傳 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:關於雲開發文件上傳的建議
總的來講就是先上傳文件,再向數據庫中寫入記錄。
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) } }) },
以上是提供的兩種思路 , 不管是否是雲開發 , 兩種思路都是共通的,適用於多文件上傳.
- 文件的下載
這個地方惟一值得注意的是雲開發的一種下載方式 能夠經過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 等 })
- 文件的移動
這個通常狀況下是用不到的, 也不建議使用移動文件的方法做爲功能實現手段 ,必然有更好的替代方式,好比修改數據庫路徑 和 真實文件路徑的映射, 效率更高一些.
這裏僅講雲開發移動文件方式。
const cloud = require('wx-server-sdk') const fs = require('fs') const path = require('path') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }) exports.main = async (event, context) => { const fileStream = fs.createReadStream(path.join(__dirname, 'demo.jpg')) //這個能夠讀取 雲存儲 中的文件 , 所謂刪除 就是複製 而後 刪除原位置文件 return await cloud.uploadFile({ cloudPath: 'demo.jpg', fileContent: fileStream, }) }
建議在數據庫中修改映射路徑最好。