微信端調取相冊或攝像頭,實現圖片上傳

前言:微信端圖片上傳遇到過很多問題,圖片太大上傳失敗,帶寬不夠,圖片上傳不完整等,今天寫這篇博客就是爲了記錄下曾經處理過的方式。同時也可以給需要的人節省點時間,採用最優解。

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("上傳失敗");
  }
});

這個倒是沒怎麼反饋說出問題,但現在又準備換成另外一種,前端直接上傳至騰訊雲,不經過後臺,這不就能從根部解決服務器壓力了嗎,恩,優秀。。。

5. 待更新…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章