为了减轻服务器的压力,公司开发的微信小程序最近开始改为使用啊里云的oss服务来存放图片。用户通过手机相册选择图片(类似发朋友圈)发表,前端调用微信接口直接把图片上传到阿里云的oss存储空间(权限设为私有),后端和前端约定图片的路径,后端拼接图片的url存放在数据库,前端从后台调来的url不能直接访问oss,要再通过签名算法,给url加上签名标签才可以访问(下面会详细讲解)。这次的oss任务交给我来完成,经过一段时间的探索,掉进过很多坑,就有了今天这篇文章,来帮助大家排坑。
开通阿里云oss服务的介绍链接
下面的步骤一、步骤二是阿里云文档给出的对oss的Bucket配置和小程序配置
1.通过 OSS 控制台查看外网域名
2.登录微信小程序平台,配置小程序的上传域名白名单。
如果你是个开发者,没有权限上传域名,可以在微信开发者工具的详情中选择项目设置,勾选不校验合法域名,这样的请求才会成功。
这是我遇到的第一个坑,浏览器的跨域请求(下面会讲一下跨域和解决浏览器跨域请求)
阿里云文档对JavaScript客户端签名直传的介绍
uploadfile下载地址
第一步:先把uploadfile下载,下载后会得到这样一个文件夹,其中upload.js是我们操作的主要部分
第二步:对upload.js的修改,找到第一张图这几个参数填进所需的数据,找到第二张图自行修改expiration的时间
第三步:运行文件夹里面的index.html到浏览器,点击上传文件,你会收到一个对象里面包括signature和policy,和一个错误。你会以为你已经成功了,兴高采烈的去微信小程序上传文件,但是你上传的时候会收到403的错误。我当时就是在这里困扰了很久,去查阿里云文档,去百度谷歌问,都没有有效的解决方法,后来发现由于浏览器的跨域请求得到的signature和policy都是错误的。
网上有很多种解决跨域的方法,这里介绍一下我是如何解决跨域请求的问题,以chrome浏览器为例子。
先简单介绍一下什么是跨域:
跨域就是:浏览器对于javascript的同源策略的限制,例如a.cn下面的js不能调用b.cn中的js,对象或数据(因为a.cn和b.cn是不同域),所以跨域就出现了.
上面提到的,同域的概念又是什么呢??? 简单的解释就是相同域名,端口相同,协议相同
这个网上有很详细的讲解
我的方法很残暴就是直接禁掉浏览器对域名的检验。方法很简单,如下:
简而言之就是点开chrome的图标修改路径,在路径最后加上–disable-web-security --user-data-dir=C:\MyChromeDevUserData,注意MyChromeDevUserData是你在C盘新建的文件夹
修改完成后,重新打开chrome,当你看到下面这个东东,你就成功了,然后再重新运行index.html,你就会发现能够成功获得signature和policy并没有报错信息。
从相册选择图片
chooseQueImg: function () {
var that = this
wx.chooseImage({
count: 1, //默认是九张
sizeType: ['original', 'compressed'],
success: function (res) {
// var QtempFilePaths = res.tempFilePaths
that.setData({
QtempFilePaths: res.tempFilePaths
})
// console.log(res.tempFilePaths)
},
})
},
上传文件到oss,控制台输出200即成功上传到oss,由于微信接口的限制,一次只能上传一张图片,如果要上传多张图片,用for循环。
wx.uploadFile({
filePath: that.data.QtempFilePaths[0],//图片的路径
url: "填oss的地址",
name: 'file',
formData: {
key: '**/**/questImage/' + '1.jpg',//图片在oss的路径
policy: "填JavaScript客户端上传获得的policy",
OSSAccessKeyId: '填AccessKeyID',
signature: '填JavaScript客户端上传获得的signature',
success_action_status: "200"
},
success: function (res) {
console.log(res)
}
直接从数据库拿到的url是不能访问oss的图片的,由于oss是按照点击请求收费的,把oss设置为私有能防止网络黑客攻击而导致费用增加。通过签名算法给url加上签名标签和访问时效,给url一个临时授权才能访问到,过了访问时间这个url又变成无效,即防盗链。
数据库中拿到的url访问oss的图片会告诉你没有权限(如果oss设置为公共可读是可以通过这样访问的哦)
这是阿里云文档给的在url包含标签的链接,有多种语言,我这次用的是JavaScript(点我)
介绍一下两种不同链接的区别吧
数据库拿到的和oss设置为公共可读的链接
https://zhouzhi-test1.oss-cn-shenzhen.aliyuncs.com/**/**/questImage/quction1.jpg
oss设置为私密的链接和我们通过签名算法得到的链接
http://zhouzhi-test1.oss-cn-shenzhen.aliyuncs.com/**/**/questImage/quction1.jpg?OSSAccessKeyId=****EkBW0VumzL&Expires=1558442185&Signature=****HAnRh3MAczVYMBFEyk%3D
可以看到有三个参数OSSAccessKeyId(即AccessKeyId)、Expires(链接失效时间)、Signature(签名算法获得的签名)
这也是我遇到的第二个坑,浪费了很多时间去读阿里云给出的JavaScript的sdk代码(主要看signatureUrl的方法),读懂后,修改代码去测试发现这份代码只是组件的一部分,下载下来是无法使用的,是一个巨坑。在CSDN,百度,谷歌看到很多java、python的方法,就是没有JavaScript(心情很烦),最后在CSDN的一篇博客中找到了(巨爽)。这个signatureUrl方法很有用,对我下面解决问题提供很大的帮助。
signatureUrl方法
发现阿里云给我们提供了封装好的组件给我们使用(这就太爽了,这只是JavaScript的,java、Python没有发现)
然后通过这一步就可以大功告成,获得可访问的链接了
Document
完成得很艰苦,但也收获很多!!!完成的时候真的会很开心,接下来继续加油!!!