您的位置:首页 > 移动开发 > 微信开发

[微信小程序]上传图片到阿里云OSS

2017-07-30 17:15 549 查看

[微信小程序]上传图片到阿里云OSS

@Author GQ 2017年07月30日

我的方法需要借助客服功能来实现,虽然繁琐,但是目的达成了~

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[/code] 
参数说明
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[/code] 

GET方法请求

参数说明
access_token调用接口凭证
type看下面
mediaform-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[/code] 

既然上传成功了,也看到图片了,下面就该上传到阿里云OSS上并返回url

阿里云官方文档有写,我后台用的是NodeJs,大家根据自己的后台看阿里文档



就是通过读取微信临时服务器图片的流到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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息