背景每个OSS用户都会用到上传服务。Web端常见的上传方式是用户在浏览器或APP端上传文件到应用服务器,然后应用服务器再将文件上传到OSS。与直接向OSS传输数据相比,上述方式存在三个缺点:上传速度慢。先上传到应用服务器,再上传到OSS,网络传输是直接传输到OSS的两倍。如果不经过应用服务器直接传给OSS,速度会大大提高,而且OSS使用BGP带宽,可以保证各地各家运营商的速度。可扩展性差。如果后续用户多了,应用服务器就会成为瓶颈。昂贵。需要准备多台应用服务器。由于OSS上传流量是免费的,如果不经过应用服务器,直接将数据传输到OSS,可以节省几个应用服务器。目的Android和IOS端实现直传有3种方式:Web端直传有3种方式:JavaScript客户端签名直传说明客户端通过JavaScript代码完成签名,然后直接传数据通过表格到OSS。服务端签名后直接传输讲解如何通过PHP代码在服务端完成签名,然后直接通过表单将数据传输到OSS。服务端签名直传和上传回调设置说明是服务端通过PHP代码完成签名,服务端设置上传后回调,然后直接通过表单将数据传给OSS。OSS回调完成后,应用服务器将结果返回给客户端。签名在客户端通过JavaScript代码完成,无需过多配置即可实现直接传输,非常方便。但是客户端通过JavaScript在代码中写入AccesssKeyID和AccessKeySecret存在泄露风险。Web端向服务器端请求签名,然后直接上传,不会对服务器端造成压力,安全可靠。但是有一个问题,就是用户上传了多少文件,上传了哪些文件。服务器无法立即知道。如果想实时知道用户上传了哪些文件,可以使用第三种方法。本文将演示如何通过第三种方式将文件直接传输到OSS服务器。demo前端window.onload=function(){letupload=document.getElementById("upload")letlink=document.getElementById("link")letobj={}//获取签名地址//consturl="http://gt-activity.gtdreamlife.com/api/oss/ossSign"axios.get(url).then(res=>{if(res.data.statusCode===200){//下面是signaturedirecttransferservice返回给客户端的消息体内容示例,该消息体内容将作为客户端上传文件的重要参数。让{dirPath,key,host,policy,Signature,callback,OSSAccessKeyId}=res.data.resultobj.host=hostobj.key=dirPath+key+"${filename}"obj.policy=policyobj.Signature=签名obj.callback=callbackobj.OSSAccessKeyId=OSSAccessKeyIdconsole.log(obj)}else{alert(res.data.message)}})document.querySelector("#file").onchange=function(e){letdata=e.target.files[0]console.log(data)letformData=newFormData()for(letkeyinobj){formData.append(key,obj[key])}//附加文件必须放在end,否则会报关键错误").value=result.data})}}服务器阿里云OSS配置信息constconfig={dirPath:'oss/file/',//如果oss文件夹不存在,会自动创建一个bucket:'${bucket}',//oss应用名region:'${region}',//oss节点名accessKeyId:'${accessKeyId}',//应用osskeyaccessKeySecret:'${accessKeySecret}',//应用osssecretcallbackPath:'api/oss/ossCallback',//回调接口expAfter:6000,//签名过期时间maxSize:1048576000,//最大文件尺寸};获取签名接口服务器返回数据回调API//图片签名asyncossSign(){const{bucket,region,expAfter,maxSize,dirPath,accessKeyId,accessKeySecret,callbackPath,}=config;consthost=`https://${bucket}.${region}.aliyuncs.com`;//你的oss完整地址//回调接口的主机和端口const{callbackHost,callbackPort}=this.app.config.oss;constexpireTime=newDate().getTime()+expAfter;constexpiration=newDate(expireTime).toISOString();constpolicyString=JSON.stringify({expiration,conditions:[['content-length-range',0,maxSize],['starts-with','$key',dirPath],],});常量策略=Buffer(policyString).toString('base64');//创建签名constSignature=crypto.createHmac('sha1',accessKeySecret).update(policy).digest('base64');constcallbackBody={//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',};constcallback=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,//文件上传地址回调,//接口回调},});}请求回调接口//callbackasyncossCallback(){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/${文件名}#w=${宽度}#h=${高度}`,});}else{this.ctx.body={status:500,message:'操作失败',data:null,};}}
