前言:微信端圖片上傳遇到過很多問題,圖片太大上傳失敗,帶寬不夠,圖片上傳不完整等,今天寫這篇博客就是爲了記錄下曾經處理過的方式。同時也可以給需要的人節省點時間,採用最優解。
1. 調用微信jssdk接口上傳
微信1.4.0版本之前給的接口如下:
1、wx.chooseImage //拍照或從手機相冊中選圖接口
2、wx.uploadImage //上傳圖片接口
3、wx.downloadImage //下載圖片接口
這種上傳方式很簡單
- 初始化jssdk接口後,可以直接調用wx.chooseImage拿到本地照片的localId(可以作爲img標籤的src屬性顯示圖片),調用方式如下:
wx.chooseImage({
count: 1, // 默認9
sizeType: ['original', 'compressed'], // 可以指定是原圖還是壓縮圖,默認二者都有
sourceType: ['album', 'camera'], // 可以指定來源是相冊還是相機,默認二者都有
success: function (res) {
var localIds = res.localIds; // 返回選定照片的本地ID列表
}
});
- 把拿到的localIds進行上傳到微信的臨時素材(有效期3天),調用方式如下:
wx.uploadImage({
localId: '', // 需要上傳的圖片的本地ID,由chooseImage接口獲得
isShowProgressTips: 1, // 默認爲1,顯示進度提示
success: function (res) {
var serverId = res.serverId; // 返回圖片的服務器端ID
}
});
- 第三步就是把serverId傳遞給後臺,由後臺去下載圖片到自己的服務器,再上傳至騰訊雲,調用方式如下:
wx.downloadImage({
serverId: '', // 需要下載的圖片的服務器端ID,由uploadImage接口獲得
isShowProgressTips: 1, // 默認爲1,顯示進度提示
success: function (res) {
var localId = res.localId; // 返回圖片下載後的本地ID
}
});
這種方式比較好用,不用自己做壓縮處理,不用考慮自己服務器帶寬的問題。就是因爲太完美了,所以微信做了限制,做了一個上限的處理。
素材管理-臨時素材上傳 | 500 |
---|---|
素材管理-臨時素材下載 | 1000 |
當天只有500的上傳量,使用的人多時,根本不夠用啊,話不多說,更新圖片上傳方式
2. 使用HTML5的input: file進行上傳
主要思想就是:在頁面中添加隱藏的input標籤(樣式太醜),每次點擊上傳時,調用input的click事件(缺點:連續選擇同一張圖片時,不進行二次上傳,不過問題不大)
<input type="file" style={{display:"none"}} ref={file => this.file=file} accept="image/*" capture="camera" multiple="multiple"/>
- 在頁面中綁定事件監聽,在這裏用到了lrz插件,用於將文件流轉化爲base64的格式並同時對圖片進行了壓縮處理
import lrz from 'lrz';
let file = this.file;
//適配蘋果選擇相冊
if (/i(Phone|P(o|a)d)/.test(navigator.userAgent)) {
$(file).removeAttr("capture");
}
file.addEventListener("change", function() {
if (this.files[0].size < 1024 * 1024 * 10) {
lrz(this.files[0])
.then(rst => {
// 處理成功會執行
util.loading.show();
uploadImg({ image: rst.base64 });
})
.catch(err => {
// 處理失敗會執行
util.toast("網絡異常,請稍後重試");
})
.always(() => {
// 不管是成功失敗,都會執行
});
} else {
util.toast("圖片大小應在10M以內");
}
});
在點擊添加圖片時,調用input的click事件,這樣就達到了效果
this.file.click();
這樣看似是沒問題了,但一直反饋說圖片上傳失敗,其實想想也是,圖片大的時候,不論怎麼壓縮,上傳都會出問題的,特別是多人同時上傳時,排隊等待就是這麼來的。怎麼辦,繼續換唄
3. 使用微信官方的轉base64的方式
我以爲是lrz插件出了問題,可能會轉碼失敗,部分轉碼不完全等原因造成的,然後就去翻官方文檔,找到這麼一個接口,如下:
wx.getLocalImgData //獲取本地圖片接口
其實一直忽略這個的主要原因還是微信給提供的 官方文檔 上面,有這麼一行小字:
備註:此接口僅在 iOS WKWebview 下提供,用於兼容 iOS WKWebview 不支持 localId 直接顯示圖片的問題
然後我就一直以爲是隻有ios才能用到。其實不然,移動端均可以使用。。。那就看下怎麼用吧!
- 添加圖片還是之前的chooseImage接口
//添加圖片
addImg() {
wx.chooseImage({
count: 1,
sourceType: ['original', 'compressed'], // 可以指定來源是相冊還是相機,默認二者都有
success: (res)=> {
var addIds = res.localIds;
var add = addIds.length;
if (add > 0) {
this.getLocalData(addIds);
}
}
});
}
- 之後再調用getLocalData(使用微信接口getLocalImgData)將圖片轉化成base64碼:
//上傳圖片
getLocalData(addIds){
addIds = addIds[0];
util.loading.show();
let upload = ()=>{
wx.getLocalImgData({
localId: addIds, //圖片的localID
success: (res)=> {
let localData = res.localData; //localData是圖片的base64數據,可以用img標籤顯示
//判斷是否有這樣的頭部
if (localData.indexOf('data:image') != 0) {
localData = 'data:image/jpeg;base64,' + localData
}
localData = localData.replace(/\r|\n/g, '').replace('data:image/jgp', 'data:image/jpeg');
this.uploadImg(localData);
},
fail: (res)=> {
util.loading.hide();
util.toast('上傳圖片異常,請嘗試切換網絡');
}
});
}
//防止微信阻止事件
setTimeout(function() {
upload();
},200);
}
本來以爲可以萬事大吉燒高香了,但還是有收到反饋說用戶上傳的圖片顯示不完整,還有的直接就不顯示,類似下面這種:
驚不驚喜意不意外,又繼續換,到這都有點不想寫了,好多東西啊,哎,來,向下看
4. 使用文件流的方式上傳,應該會減少點服務器壓力
思想還是之前的那種,用input獲取到圖片文件流,直接傳給後臺作處理,唯一需要注意的可能就是給後臺傳數據時,需要傳遞formData對象,代碼如下:
const formData = new FormData();
formData.append("file", file[0]);
$.ajax({
url: baseUrl,
type: "POST",
data: formData,
timeout: 10000,
cache: false,
processData: false,
contentType: false,
success: result => {
console.log("成功上傳");
},
error: result => {
console.log("上傳失敗");
}
});
這個倒是沒怎麼反饋說出問題,但現在又準備換成另外一種,前端直接上傳至騰訊雲,不經過後臺,這不就能從根部解決服務器壓力了嗎,恩,優秀。。。