每一个OSS的用户都会用到上传服务。Web端常见的上传方法是用户在浏览器或app端上传文件到应用服务器,而后应用服务器再把文件上传到OSS。html
和数据直传到OSS相比,以上方法有三个缺点:前端
Web端直传共有三种方式:ios
在客户端经过JavaScript代码完成签名,无需过多配置,便可实现直传,很是方便。可是客户端经过JavaScript把AccesssKeyID 和AccessKeySecret写在代码里面有泄露的风险。web
web端向服务端请求签名,而后直接上传,不会对服务端产生压力,并且安全可靠。然而有个问题,就是用户上传了多少文件,上传了什么文件,服务端并不能立刻知道,若是想实时了解用户上传了什么文件,能够采用第三种方式。json
本文将演示如何经过第三种方式完成文件直传到OSS服务器。axios
window.onload = function () { let upload = document.getElementById("upload") let link = document.getElementById("link") let obj = {} // 获取签名地址 // const url = "http://gt-activity.gtdreamlife.com/api/oss/ossSign" axios.get(url).then(res => { if (res.data.statusCode === 200) { // 下面是签名直传服务返回给客户端的消息body内容的示例,这个body的内容将做为客户端上传文件的重要参数。 let { dirPath, key, host, policy, Signature, callback, OSSAccessKeyId } = res.data.result obj.host = host obj.key = dirPath + key + "${filename}" obj.policy = policy obj.Signature = Signature obj.callback = callback obj.OSSAccessKeyId = OSSAccessKeyId console.log(obj) } else { alert(res.data.message) } }) document.querySelector("#file").onchange = function (e) { let data = e.target.files[0] console.log(data) let formData = new FormData() for (let key in obj) { formData.append(key, obj[key]) } // append 文件必须放在最后,否则会报key错误 formData.append("file", data) axios.post(obj.host, formData).then(res => { const result = res.data document.querySelector("#link").value = result.data }) } }
阿里云OSS配置信息api
const config = { dirPath: 'oss/file/', // oss 文件夹 不存在会自动建立 bucket: '${bucket}', // oss应用名 region: '${region}', // oss节点名 accessKeyId: '${accessKeyId}', // 申请的osskey accessKeySecret: '${accessKeySecret}', // 申请的osssecret callbackPath: 'api/oss/ossCallback', // 回调接口 expAfter: 6000, // 签名失效时间 maxSize: 1048576000, // 最大文件大小 };
获取签名接口
服务器返回数据Callback API浏览器
// 图片签名 async ossSign() { const { bucket, region, expAfter, maxSize, dirPath, accessKeyId, accessKeySecret, callbackPath, } = config; const host = `https://${bucket}.${region}.aliyuncs.com`; // 你的oss完整地址 // 回调接口的主机和端口 const { callbackHost, callbackPort } = this.app.config.oss; const expireTime = new Date().getTime() + expAfter; const expiration = new Date(expireTime).toISOString(); const policyString = JSON.stringify({ expiration, conditions: [ [ 'content-length-range', 0, maxSize ], [ 'starts-with', '$key', dirPath ], ], }); const policy = Buffer(policyString).toString('base64'); // 建立签名 const Signature = crypto.createHmac('sha1', accessKeySecret).update(policy).digest('base64'); const callbackBody = { // callbackUrl为 上传回调服务器的URL,请将下面的IP和Port配置为您本身的真实信息。 callbackUrl: `https://${callbackHost}${callbackPort ? `:${callbackPort}` : ''}/${callbackPath}`, callbackHost: `${callbackHost}`, // 规定返回数据的格式,当前默认返回图片信息、宽度、高度,可获取更多数据。参考上方连接 callbackBody: '{"filename": ${object},"size": ${size},"width": ${imageInfo.width},"height": ${imageInfo.height}}', callbackBodyType: 'application/json', }; const callback = Buffer(JSON.stringify(callbackBody)).toString('base64'); this.ctx.body = ({ statusCode: 200, message: 'oss签名成功', result: { Signature, // 对变量policy签名后的字符串。 policy, // 用户表单上传的策略(Policy),是通过base64编码过的字符串。 host, // 用户要往哪一个域名发送上传请求。 OSSAccessKeyId: accessKeyId, // 用户请求的accessid。 key: expireTime, // 惟一标识,添加到上传的文件名中防止重复 success_action_status: 200, dirPath, // 文件上传地址 callback, // 接口回调 }, }); }
请求回调接口安全
// 回调 async ossCallback() { const { body = {} } = this.ctx.request; // 对应签名接口中定义的返回数据字段 const { filename, height, width } = body; if (filename) { this.ctx.body = ({ status: 200, message: '操做成功', data: `https://${config.bucket}.${config.region}.aliyuncs.com/${filename}#w=${width}#h=${height}`, }); } else { this.ctx.body = { status: 500, message: '操做失败', data: null, }; } }