通过 对象存储OSS 购买服务后 ,该步骤主要配置 region、bucket ,再通过 AccessKey管理 获取到服务 accessKeyId、accessKeySecret ,即得到如下信息:
{
"region": "region",
"bucket": "bucket",
"AccessKey": "AccessKey",
"accessKeySecret": "accessKeySecret",
// 用于服务端签名后直传,设置上传回调
"callback": "callback",
// 用于服务端签名后直传,设置上传回调接口认证
"x-csrf-token": "x-csrf-token"
}
服务器端签名直传,首先是后端会提供一个接口,前端请求该接口后会返回一些字段数据,即以上关键信息;
服务端验证上传
先将文件传递到应用服务器,再由应用服务器上传至oss服务器,这种方式的优势是简单易懂,只须要按照文档使用ali-oss中间件上传就行,本文重点不放在这种方式;
这种方式缺点是,文件要先上传到应用服务器,再上传到oss,占用带宽资源,过程简单,调用服务端接口;
服务端签名前端直传
在客户端通过JavaScript代码完成签名,无需过多配置,即可实现直传,非常方便。但是客户端通过JavaScript把AccesssKey ID和AccessKey Secret写在代码里面有泄露的风险,强烈建议使用服务端签名后直传或者STS临时授权访问OSS;
该方式分为两种上传方案:
oss-js-sdk
,即 ali-oss
上传文件;axios
,wx.uploadFile
等,本文主要对该方式进行配置说明; 通过第三方请求工具上传,如 axios
,wx.uploadFile
等;
大多数情况下,用户上传数据后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,为此OSS提供了上传回调方案;
具体参数说明,参考阿里云 - 帮助中心 - PostObject,必要配置参数如下:
{
"OSSAccessKeyId": "OSSAccessKeyId",
// 通过 crypto-js 生成,或直接从后端获取
"policy": "policy",
"success_action_status": "200",
// 该参数为非必要参数,用于实现上传回调方案
"callback": "callback",
"name": "filename",
"key": "application/${filename}",
// 通过 crypto-js 生成,或直接从后端获取
"Signature": "Signature",
}
// npm install ali-oss --save
// <script type="text/javascript" src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.16.0.min.js"></script>
const client = new OSS({
// yourregion填写Bucket所在地域。
// 以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
region: 'oss-cn-hangzhou',
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。
// 强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
accessKeyId: 'accessKeyId',
accessKeySecret: 'accessKeySecret',
// 填写Bucket名称。关于Bucket名称命名规范的更多信息,请参见Bucket。
bucket: 'xx-bucket',
});
const headers = {
...
};
try {
const result = await client.put(
"application/exampleSmile.png",
data
// {headers}
);
console.log(result);
} catch (e) {
console.log(e);
}
// 当前环境为 NodeJS 环境,实际生产环境中注意选择合适插件;
const crypto = require('crypto');
const { Buffer } = require("buffer");
const { Base64 } = require('js-base64');
const accesskey = "accesskey";
// 10分钟后过期
const timestamp = Date.now() + 10 * 60 * 1000;
const policyText = {
// 设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件
"expiration": `${new Date(timestamp).toISOString()}`,
"conditions": [
// 设置上传文件的大小限制
["content-length-range", 0, 1024 * 1024 * 2]
]
};
const callbackJSON = {
// 服务端回调接口地址
callbackUrl: 'callbackUrl',
// 所需返回的文件信息配置
callbackBody:
"filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}",
callbackBodyType: "application/x-www-form-urlencoded",
}
const policy = Base64.encode(JSON.stringify(policyText));
const signature = crypto.createHmac("sha1", accesskey)
.update(policyBase64)
.digest()
.toString("base64");
const callback = Buffer.from(JSON.stringify(callbackJSON)).toString("base64");
function fileCreate (file) {
const uploadData = new FormData();
uploadData.append("OSSAccessKeyId", 'OSSAccessKeyId');
uploadData.append("key", 'application/${filename}');
uploadData.append("policy", "policy");
uploadData.append("success_action_status", 200);
// uploadData.append("callback", "callback");
uploadData.append("name", file.name);
uploadData.append("Signature", "Signature");
uploadData.append("file", file);
return uploadData;
}
const uploadData = fileCreate (file);
axios({
// 您的OSS访问域名,格式为BucketName.Endpoint,例如 post-test.oss-cn-hangzhou.aliyuncs.com;
url: 'http://post-test.oss-cn-hangzhou.aliyuncs.com',
method: 'post',
data: uploadData,
headers: { 'Content-Type': 'multipart/form-data' }
}).then(r => console.log(r));
// 通过 wx.chooseImage 函数获取到返回值
const tempFilePaths = res.tempFilePaths;
wx.uploadFile({
// 您的OSS访问域名,格式为BucketName.Endpoint,例如 post-test.oss-cn-hangzhou.aliyuncs.com;
url: 'http://post-test.oss-cn-hangzhou.aliyuncs.com',
filePath: tempFilePaths[0],
name: 'file',
formData: {
name: tempFilePaths[0],
key: 'application/${filename}',
policy: policy,
OSSAccessKeyId: OSSAccessKeyId,
signature: signature,
success_action_status: '200',
callback: OSSCallback,
},
success(res) {
//do something
if (200 === res.statusCode) console.log(res);
},
});