开发 | 手把手,教你为小程序添加「上传图片」功能
知晓程序注:
很多小程序都为用户提供图片上传功能。这时候,使用一些「对象存储」云服务,也许是最快、最经济的选择。
那么,小程序该如何使用这类服务呢?使用的时候,又应该注意哪些问题呢?
知晓程序(微信号 zxcx0101)今天分享的这篇文章,会以腾讯云的对象存储服务为例,教大家将小程序接入对象存储服务。
文 | goodspeed
准备工作
上传图片,主要是将图片上传到腾讯云对象存储(COS)。
要使用对象存储 API,需要先执行以下步骤:
- 购买腾讯云对象存储(COS)服务。
- 在腾讯云 对象存储控制台 里创建一个 Bucket。
- 在控制台「个人 API 密钥」页面里,获取 AppID、SecretID、SecretKey 等内容
- 编写一个请求签名算法程序(或使用任何一种服务端 SDK)
- 计算签名,调用 API 执行操作
所以,我们要做的准备工作有:
- 进入腾讯云官网(www.qcloud.com),注册帐号。
- 登录云对象存储服务(COS)控制台,开通 COS 服务,创建资源需要上传的 Bucket。
- 在公众平台小程序后台中,配置相关域名信息(否则无法在小程序中发起对该域名的请求)。
这些配置过程这里就不做说明了,接下来主要介绍步骤 4 和 5。
小程序上传图片到 COS 的流程图,如下:
在这个过程中我们需要实现的是,鉴权服务器返回签名的步骤,以及小程序处理图片的相关步骤。
COS 鉴权服务
使用对象存储服务 COS 时,可通过 RESTful API,对 COS 发起 HTTP 匿名请求或签名请求。
对于签名请求,COS 服务器端将会进行对请求发起者的身份验证。
- 匿名请求:HTTP 请求不携带任何身份标识和鉴权信息,通过 RESTful API 进行 HTTP 请求操作。
- 签名请求:HTTP 请求时添加签名,COS 服务器端收到消息后,进行身份验证,验证成功则可接受并执行请求,否则将会返回错误信息并丢弃此请求。
腾讯云 COS 对象存储,基于密钥 HMAC(Hash Message Authentication Code)的自定义 HTTP 方案,进行身份验证。
在此例中,上传图片是一个签名请求,需要进行签名验证。
1. 签名流程
客户通过对 HTTP 请求进行签名,并将签名后的请求发送至腾讯云进行签名验证,具体流程如下图所示。
我们使用 SDK 开发,只需要大致了解这个流程就行。在 SDK 中已包含签名的实现,我们只需要调用 SDK 中的方法即可。
通过签名流程我们可以知道,签名需要 SecretId
和 SecretKey
,这两个信息不适合存放在客户端中,这也是我们单独部署一个鉴权服务器的主要原因。
2. 生成签名的接口
在之前的文章中,我介绍过,我在服务端使用 sanic
框架和 swagger_py_codegen
生成 Rest API。
为了完成签名生成 API,我们需要先在文档中添加 API 的相关描述。
/qc_cos/config:
get:
summary: 腾讯云配置
description: 腾讯云配置
tags: [Config]
operationId: get_qc_cos_config
parameters:
- $ref: '#/parameters/AccessToken'
- $ref: '#/parameters/qcos_path_in_query'
responses:
200:
schema:
$ref: '#/definitions/QCOSConfig'
default:
description: Unexpected error
schema:
$ref: '#/definitions/Error'
security:
- OAuth2: [open]
这个接口我们要求登录才能调用。
文档定义完成之后,调用 swagger_py_codegen -s docs/v1.yml . -p apis -tlp sanic
生成代码模板。API 代码实现如下:
from qcloud_cos.cos_auth import Auth
from qcloud_cos.cos_auth import Auth
async def get(self, request):
auth = Auth(appid=Config.QCOS_APPID,
secret_id=Config.QCOS_SECRET_ID,
secret_key=Config.QCOS_SECRET_KEY)
expired = time() + 3600 # 签名有效时间 3600 秒
# 上传到 cos bucket 的目录
dir_name = request.raw_args.get('cos_path', '/xrzeti')
# 生成签名
sign = auth.sign_more(Config.QCOS_BUCKET_NAME,
cos_path=dir_name,
expired=expired)
return {"sign": sign}, 200
由于腾讯云 COS v4 的 Python SDK 只支持 Python 2,而 sanic 需要 Python 3.5+,所以,这里我 fork 出来一份添加了 Python 3 的支持,使用 Python 3 的开发者,可以使用它。
关注「知晓程序」微信公众号,回复「源码」,获取该框架下载地址。
在小程序上传图片
1. 选择图片
wx.chooseImage(OBJECT)
从本地相册选择图片或使用相机拍照。
调用这个方法,小程序会把选择的图片放到临时路径,在小程序本次启动期间可以正常使用。
如需持久保存,需再调用 wx.saveFile
,在小程序下次启动时才能访问。
在小程序中,我们只能上传临时路径的文件。
核心代码如下:
uploadToCos: function () {
var that = this;
// 选择上传的图片
wx.chooseImage({
sizeType: ['original', 'compressed'], // 图片类型 original 原图,compressed 压缩图,默认二者都有
success: function (res) {
// 获取文件路径
var file = res.tempFiles[0];
console.log(file.size);
// 获取文件名
var fileName = file.path.match(/(wxfile:\/\/)(.+)/)
fileName = fileName[2]
// 获取到图片临时路径后,指定文件名 上传到 cos
upload(file.path, fileName, that);
}
})
}
这里图片选择成功后,我们取原图上传到 COS。
2. 上传图片
COS 上传图片的 URL,由 cos_region
,appid
,bucket_name
和 cos_dir_name
等参数拼接而成。
把以下字段配置成自己的 COS 相关信息(详情可看 API 文档):
cosUrl = "https://" + REGION + ".file.myqcloud.com/files/v2/" + APPID + "/" + BUCKET_NAME + DIR_NAME;
REGION
:COS 上传的地区APPID
:账号的 appidBUCKET_NAME
:COS Bucket 的名字DIR_NAME
:上传的文件目录
var config = require('../config.js');
// 先确定上传的 URL
var cosUrl = "https://" + config.cos_region + ".file.myqcloud.com/files/v2/" + config.cos_appid + "/" + config.cos_bucket_name + config.cos_dir_name;
//填写自己的鉴权服务器地址
var cosSignatureUrl = config.host + '/v1/qc_cos/config?cos_path=' + config.cos_dir_name;
/**
* 上传方法
* filePath: 上传的文件路径
* fileName: 上传到 cos 后的文件名
* that: 小程序所在当前页面的 object
*/
function upload(filePath, fileName, that) {
var data;
// 鉴权获取签名
wx.request({
url: cosSignatureUrl,
header: {
Authorization: 'JWT' + ' ' + that.data.jwt.access_token
},
success: function (cosRes) {
// 获取签名
var signature = cosRes.data.sign;
// 头部带上签名,上传文件至 COS
var uploadTask = wx.uploadFile({
url: cosUrl + '/' + fileName,
filePath: filePath,
header: {
'Authorization': signature
},
name: 'filecontent',
formData: {
op: 'upload'
},
success: function (uploadRes) {
// 上传成功后的操作
var upload_res = JSON.parse(uploadRes.data)
var files = that.data.files;
files.push(upload_res.data.source_url);
that.setData({
upload_res: upload_res,
files: files,
test_image: upload_res.data.source_url
})
},
fail: function (e) {
console.log('e', e)
}
});
// 上传进度条
uploadTask.onProgressUpdate((res) => {
that.setData({
upload_progress: res.progress
})
if (res.progress === 100){
that.setData({
upload_progress: 0
})
}
})
}
})
return data
}
小程序提供了 uploadTask.onProgressUpdate()
来获取图片的上传进度,所以在这里,我将图片的上传进度显示了出来。
最后,感谢女朋友支持。
原文地址:https://juejin.im/post/59a23fff518825244d204d9e
关注「知晓程序」公众号 👇
- 在微信后台回复「开发」,获取知晓程序开发全套经验。
- 在微信后台回复「666」,获取小程序开发 demo。