[微信小程序]上傳圖片到阿里雲OSS

[微信小程序]上傳圖片到阿里雲OSS

@Author GQ 20170730日  

我的方法需要藉助客服功能來實現,雖然繁瑣,但是目的達成了~

1.將小程序選擇的照片上傳至微信臨時服務器並返回圖片url;(需要開通客服功能)
2.將url返回給自己的後臺,後臺通過url獲取流再上傳至阿里OSS;

這裏實現第二步:

關於如何開通客服功能的消息的配置可以看我的上一篇博客點我查看


上傳圖片到微信臨時服務器

首先要獲取到access_token,有效期2小時,token詳情看這裏

GET方法請求

//獲取access_token
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
參數 說明
grant_type 填 client_credential
appid 第三方用戶唯一憑證
secret 上微信公衆平臺小程序掃二維碼查看

返回

//獲取成功返回
{
    "access_token": "ACCESS_TOKEN",
    "expires_in": 7200
}

拿到access_token後就可以上傳臨時文件了

//上傳臨時文件
https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE

GET方法請求

參數 說明
access_token 調用接口憑證
type 看下面
media form-data中媒體文件標識
  • 圖片(image): 1M,支持JPG格式
  • 語音(voice):2M,播放長度不超過60s,支持AMR\MP3格式
  • 視頻(video):10MB,支持MP4格式
  • 縮略圖(thumb):64KB,支持JPG格式
  • 媒體文件在後臺保存時間爲3天,即3天后media_id失效。

各位記住了詳情看這裏

返回

//上傳成功返回
{
    "type": "image",
    "media_id": "R-Y5NXGd1tUUeKKEX37eV5q63MoPNQKW8xpnb_29Z3Yp22flghiZIRuGny0uYBRZ",
    "created_at": 1501137599
}
  • 這裏的media_id就是剛纔上傳的文件,怎麼打開呢?不要慌!

微信官方調試工具即可查看剛纔上傳的圖片

如果出現下圖的樣子,就表示success了,但是圖片不應該是返回url嗎 ? 怎麼返回只有個header

  • 其實返回的是圖片的流

上傳層高

  • 如果想要看一下圖片呢,可以在瀏覽器直接輸下面這段就會提示下載圖片,參數上面都有
//獲取文件
https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID

既然上傳成功了,也看到圖片了,下面就該上傳到阿里雲OSS上並返回url

阿里雲官方文檔有寫,我後臺用的是NodeJs,大家根據自己的後臺看阿里文檔

上傳文件阿里雲node

  • 就是通過讀取微信臨時服務器圖片的流到OSS並轉成圖片存起來,然後返回給咱們阿里的圖片url

呵(ni)呵(mei)噠(de)~官方總是寫的簡單難懂,能少寫就少寫!

我貼一下Node後臺上傳圖片的代碼

var express = require('express');
var router = express.Router();
var fs = require('fs');
var commonResult = require('../../service/commonResult');



//阿里雲OSS
var co = require('co');
var OSS = require('ali-oss');

var client = new OSS({
    region: 'oss-cn-beijing',//填自己的
    accessKeyId: 'xxx',//填自己的
    accessKeySecret: 'xxx',//填自己的
    endPoint: 'http://oss-cn-beijing.aliyuncs.com',//如果指定了endpoint,則region會被忽略
    bucket: 'xxx'//填自己的
});

//上傳圖片文件
router.post('/uploadFile', function (req, res, next) {
    var url = req.body.url;//這個url是微信小程序直接全部傳過來的,就是剛纔直接複製在瀏覽器就能下載到圖片的那個。打印出來是這樣的: https://api.weixin.qq.com/cgi-bin/media/get?access_token=ACCESS_TOKEN&media_id=MEDIA_ID

    var timestamp = new Date().getTime();
    var path = './test';
    var key = 'test/' + timestamp;

    //選擇bucket
    client.useBucket('xxx');//填自己的

    //獲取遠程文件,並以流寫入文件
    console.log("微信臨時文件地址 = " + url)
    var stream = request(url).pipe(fs.createWriteStream(path));
    stream.on('error', function (err) {
        console.log(err);
    });
    //流寫入完畢
    stream.on('finish', function () {
        co(function*() {
            var result = yield client.put(key, path);
            console.log(result);
            commonResult.returnSuccess(res, result.url);
        }).catch(function (err) {
            console.log(err);
            commonResult.returnFailed(res, "上傳失敗");
        });
    });
});


module.exports = router;
  • commonResult是一個返回Json格式數據的稍微封裝了一下
var CommonResult = require('../models/commonResult');

/**
 * 返回失敗
 * @param err
 * @param res
 */
exports.returnFailed = function (res, err) {
    var commonResult = new CommonResult();
    commonResult.success = false;
    commonResult.message = err;
    commonResult.data = null;
    res.send(commonResult);
};

/**
 * 返回成功
 * @param res
 */
exports.returnSuccess = function (res, data) {
    var commonResult = new CommonResult();
    commonResult.success = true;
    commonResult.message = "獲取成功";
    if (data != null && data != "") {
        commonResult.data = data;
    } else {
        commonResult.data = null;
    }
    res.send(commonResult);
};
  • 當然有個實體CommonResult
function CommonResult() {
    this.success;
    this.message;
    this.data;
}

module.exports = CommonResult;

注意引入的路徑問題,看自己項目的路徑自行修改下,Node後臺就回返回給微信小程序一個上傳完成的url地址了,這樣可以直接點擊url查看圖片了,然後拿到url該幹嘛幹嘛~

微信小程序上傳圖片代碼

...

//我這裏直接獲取access_token了,根據自己的需要在程序入口或者其他地方獲取一次和判斷超時重新獲取即可
//點擊拍照事件自己綁定,我的bindTap = "onTakePhotoClick"

/**
  * 點擊拍照
  */
  onTakePhotoClick: function () {
    var that = this;
    //讀取保存的token
    this.data.access_token = wx.getStorageSync("ACCESS_TOKEN");
    console.log('讀取ACCESS_TOKEN = ' + this.data.access_token)
    if (this.data.access_token == '') {
      //獲取AccessToken
      that.getAccessToken(function () {
        //拍照
        that.takePoto()
      });
    } else {
      //拍照
      that.takePoto()
    }
  },

  /**
   * 獲取AccessToken
   */
  getAccessToken: function (callback) {
    wx.request({
      url: 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=' + appId + '&secret=' + appSecret,
      success: function (res) {
        var access_token = res.data.access_token
        if (access_token) {
          //獲取access_token成功並保存
          wx.setStorageSync("ACCESS_TOKEN", access_token)
          console.log('獲取並保存ACCESS_TOKEN = ' + access_token)
          callback()
        }
      },
      fail: function (err) {
        wx.showToast({ title: '獲取token失敗', image: '../../images/icon_err.png', })
      }
    })
  },

  /**
   * 拍照
   */
  takePoto: function () {
    var that = this;

    wx.chooseImage({
      count: 1,
      sizeType: ['compressed'],
      sourceType: ['camera'],
      success: function (res) {
        var path = res.tempFilePaths[0]
        //上傳
        that.uploadPhoto(path)
      }
    })
  },

  /**
   * 上傳
   */
  uploadPhoto: function (path) {
    var that = this
    var imgPath = path
    wx.showLoading({
      title: '照片上傳中',
    })
    wx.uploadFile({
      url: 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=' + this.data.access_token + '&type=image',
      filePath: path,
      name: 'media',
      success: function (res) {
        wx.hideLoading();
        var obj = JSON.parse(res.data.trim());
        console.log('上傳到微信臨時服務器 = ' + res.data)
        if (obj.errcode && obj.errcode > 42000) {
          //說明token超時,需再次獲取
          that.getAccessToken(function () {
            that.uploadPhoto(imgPath)
          });
        } else {
          //後臺再根據access_token和media_id獲取臨時文件
          that.getTempFile(obj.media_id);
        }
      },
      fail: function (err) {
        wx.hideLoading();
        wx.showToast({ title: '微信臨時服務器連接失敗', image: '../../images/icon_err.png', })
        console.log(err)
      }
    })
  },

  /**
   * 獲取微信服務器上的臨時文件
   * 
   */
  getTempFile: function (media_id) {
    var that = this;
    console.log('media_id = ' + media_id)
    wx.showLoading({
      title: '照片加載中',
    })
    wx.request({
      url: IP_Node + 'api/common/uploadFile',
      method: 'POST',
      data: {
        url: 'https://api.weixin.qq.com/cgi-bin/media/get?access_token=' + this.data.access_token + '&media_id=' + media_id,
      },
      success: function (res) {
        wx.hideLoading();
        if (res.data.success) {
          console.log('獲取oss圖片的url = ' + res.data.data);
          that.setData({
            iv_url: res.data.data,//顯示圖片
          })
          wx.showToast({ title: '照片上傳成功', icon: 'success', })
        } else {
          wx.showToast({ title: '照片上傳失敗', image: '../../images/icon_err.png', })
        }
      },
      fail: function (err) {
        wx.hideLoading();
        console.log(err)
        wx.showToast({ title: '失敗:' + err, image: '../../images/icon_err.png', })
      }
    })
  },

小程序文檔裏確實有個拓展接口

wx.base64ToArrayBuffer(base64)

當然,小程序上傳的圖片直接轉化爲流直接post上傳是最佳的選擇,但是查了許多資料都沒能實現,還望有大神指導~

//網上資料都是這個,不能用還是不會用???!!!
var uploadImage = this.data.imageList[0]
var reader = new FileReader()
reader.onload = function (e) {
      var arrayBuffer = reader.result;
      var base64 = wx.arrayBufferToBase64(arrayBuffer)
}
reader.readAsArrayBuffer(new Blob(this.data.imageList))
發佈了69 篇原創文章 · 獲贊 16 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章