浅显易懂,轻松搞定OSS的签名直传头像功能
自己的网站(https://www.gf-app.cn)目前只做了第三方登录。主要是考虑用手机号登录,就得接短信验证码服务。怕被人恶意刷短信,就得做防刷机制,否则有被刷短信费的风险。
初次登录会自动获取客户在支付宝的头像和昵称来自动注册。客户可以通过修改资料的重新上传头像。
茴香豆的“茴”字有五种写法,上传头像的方法,同样有5种。
建议都使用第三方图床(以阿里云OSS为例)。主要是看中了能够自由缩放图片尺寸。这5种方法具体的优缺点评比见后面的表格。
- 直接将图片上传到自己的服务器。
就是图片通过表单提交到后台,后台将图片保存到自己服务器的某个地方后,继续后续逻辑。
难度:☆
推荐度:☆
- 简单,这是最基本的功能实现,一个后台就可完成;
- 所有图片都保存在自己的服务器上,占用了硬盘空间。而硬盘空间是需要花钱买的;
- 图片越多,花费越高!不推荐。
- 先上传再转存图床(使用OSS)
先用方法1实现将图片上传到自己的服务器,再调用阿里云OSS的sdk,将图片转存过去。
难度:☆☆
推荐度:☆☆
- 难度方面,相对方法1,添加了转存的逻辑。由于有现成的sdk供调用,只要要学习oss怎样配置就可。一个后台就可完成;
- 因为图片还是得先上传到自己服务器,仍然避免不了占用硬盘的问题。而且为了节省硬盘,还需要写代码清除自己服务器的图片。此外转存带来了图片的二次上传,代码的执行时间会变的更长;
- 在项目的前期研发阶段,可以当做临时方案使用。
- javascript直传
前台直传需要用到安全加密算法的数字签名。这种方法里,签名由前台生成,生成好的签名和图片即可以一律由前台代码发到OSS端了,解放了后台。
难度:☆☆☆(前台)
推荐度:☆☆
- 需要学习如何生成数字签名,一个前台可以搞定;
- 由于是直接上传,所以不会占用服务器硬盘;
- 因为签名需要前台生成,所以敏感性数据比方access_id_key就得写到js代码里了。前台代码几乎是透明的,假如有懂的人,直接把你的密钥拿走干别的了,你还得傻乎乎的给人家续费;
- 有安全风险,不推荐!
- 服务端签名后javascript直传
流程和方法3类似,只是数字签名交给了后台。javascript带着签名将图片上传给OSS。
难度:☆☆☆☆
推荐度:☆☆☆☆☆
- 后台需要生成加密签名,并提供给前台使用,这里有少量难度,不过可以参考阿里云的demo ,需要前后台进行配合;
- 这种方法很好用,但是有肯定的业务局限性。比方客户上传了照片,但是不点击保存就把网页关了,那oss空间就白白白费了。
- 根据自身业务选择,强烈推荐!
- 服务端签名直传后设置回调
流程相比照方法4,添加了回调逻辑。后台先生成签名,js带着签名上传图片之后,阿里云会主动调用你提供的接口完成后续操作。
难度:☆☆☆☆☆
推荐度:☆☆☆☆
- 和方法4相比,几乎没有缺点,也不怕客户中途关闭网页,没有业务局限性。
- 生成签名时需要添加回调地址和回传参数。
- 尽管有demo参考,但回调地址必需在公网环境下才能调试,不太方便;
- 由于不好调试,比较推荐。
优缺点对照表
图片上传对照.png
编码部分
在我这次的修改头像逻辑中,我选择了方法4。假如客户一次只选择一张图片,那么其实可以用选择好图片立即上传的方法,不给客户不点“上传”按钮的机会。由于客户是最懒的,不要妄图教育客户,能让他点一下,就不应该让他点第二下。
阿里云提供的服务器签名直传的demo是这样的,需要让人点两下,这不符合我的设计。
oss的上传demo.png
所以我们需要对这个demo里的代码进行修改,以实现我们一次点击完成上传的需求。
这个js的demo,是基于plupload-2.1.2版本。我们需要重新定义FilesAdded事件的解决逻辑。下载了阿里云的demo后,打开upload.js,可以看见这样的代码:
FilesAdded: function(up, files) { plupload.each(files, function(file) { document.getElementById('ossfile').innerHTML += '<div id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ')<b></b>' +'<div class="progress"><div class="progress-bar" style="width: 0%"></div></div>' +'</div>'; }); },
这个FilesAdded事件,就是当plupload组件拿到要上传的图片之后触发的。阿里云的demo是显示你选择的图片名和文件大小。而我的逻辑则需要直接触发上传。所以我的代码是这样写的:
// 增加文件uploader.bind("FilesAdded", function (up, files) { set_upload_param(up); return false;});
这样一来,我的上传体验就变成了这样:
我的上传.png
操作起来是这样的:
uxdf0-75bsm.gif
怎样样,体验一下子就好多了吧!
附上完整的代码:
前台javascript
var oss_token = {{ oss_token }}// 上传签名,这里直接输出在页面了。建议头像上传之后自动刷新一下页面。这个token只能用一次。当然你也可以使用同步ajax去服务端获取。// console.log(oss_token);// console.log(current_uid);// 设置上传参数function set_upload_param(up) { // 获取上传签名 obj = oss_token; host = obj['host']; policyBase64 = obj['policy']; accessid = obj['accessid']; signature = obj['signature']; expire = parseInt(obj['expire']); callbackbody = obj['callback']; key = obj['dir'] + "/" + current_uid; //头像的地址就用user_id来当做key了,可以通过拼接拿到地址,减少读库。 timestamp = Date.parse(new Date()) / 1000; new_multipart_params = { 'key': key, 'policy': policyBase64, 'OSSAccessKeyId': accessid, 'success_action_status': '200', //让服务端返回200,不然,默认会返回204 // 'callback' : callbackbody, 'signature': signature, }; console.log(new_multipart_params); up.setOption({ 'url': host, 'multipart_params': new_multipart_params }); up.start();}// 取得头像路径function get_avatar_path() { obj = oss_token; host = obj['host']; key = obj['dir'] + "/" + current_uid; timestamp = Date.parse(new Date()) / 1000; return host + "/" + key + "?v=" + timestamp; //通过修改的时间戳作为附加参数,可以防止浏览器缓存或者cdn导致图片不升级}// 实例化上传组件var uploader = new plupload.Uploader({ runtimes : 'html5,flash,silverlight,html4', browse_button : 'selectfiles', //选择文件按钮的元素ID flash_swf_url : 'lib/plupload-2.1.2/js/Moxie.swf', silverlight_xap_url : 'lib/plupload-2.1.2/js/Moxie.xap', url : 'http://oss.aliyuncs.com', filters: { mime_types: [ //只允许上传图片 {title: "Image files", extensions: "jpg,jpeg,gif,png"}, ], max_file_size: '5mb', //最大只能上传5mb的文件 prevent_duplicates: true //不允许选取重复文件 },});uploader.init();/** 绑定方法 **/// 增加文件uploader.bind("FilesAdded", function (up, files) { set_upload_param(up); //组装签名,执行上传 return false;});//上传成功uploader.bind("FileUploaded", function (up, file, info) { if (info.status == 200) { // 将新头像地址保存到数据库 } else { errorMsg("上传失败"); }});//弹出错误提醒function errorMsg(msg) { var tips = $('#topTips_avatar'); tips.text(msg); tips.fadeIn(100); setTimeout(function () { tips.fadeOut(100); }, 2000);}
相对完整的python后台代码
# manage.py# 获取直传token def get_token(self, bucket_name, prefix=""): now = int(time.time()) expire_syncpoint = now + self.expire_time # expire_syncpoint = 1612345678 expire = OssTokenManager.get_iso_8601(expire_syncpoint) policy_dict = {} policy_dict['expiration'] = expire condition_array = [] array_item = [] array_item.append('starts-with') array_item.append('$key') array_item.append(prefix) condition_array.append(array_item) policy_dict['conditions'] = condition_array policy = json.dumps(policy_dict).strip() policy_encode = base64.b64encode(policy.encode()) h = hmac.new(OSS_ACCESS_KEY_SECRET.encode(), policy_encode, sha) sign_result = base64.encodebytes(h.digest()).strip() token_dict = {} token_dict['accessid'] = OSS_ACCESS_KEY_ID token_dict['host'] = "http://%s" % self.get_domain(bucket_name) token_dict['policy'] = policy_encode.decode() token_dict['signature'] = sign_result.decode() token_dict['expire'] = expire_syncpoint token_dict['dir'] = prefix # token_dict['callback'] = base64_callback_body.decode() result = json.dumps(token_dict) return result def get_domain(self, bucket_name): # print(bucket_name) if bucket_name in OSS_BUCKETNAME: return OSS_BUCKETNAME[bucket_name]["domain"] else: return ""
# config.py# oss配置OSS_ACCESS_KEY_ID = 'abcd1234' //改成你自己的OSS_ACCESS_KEY_SECRET = '1234abcd' //改成你自己的OSS_END_POINT = 'http://oss-cn-beijing.aliyuncs.com' //改成你自己的# bucket设置 {类别/用途:{bucket:BUCKET, domain:域名, style:[STYLE]}OSS_BUCKETNAME = { # 头像 "avatar": {"bucket": 'xx-avatar', "domain": "xx-avatar.oss-cn-beijing.aliyuncs.com", "style": ["avatar_middle_w80h80"]},}
这份文档就写在这里了,快去试试吧!假如有帮助,请帮我点个赞。假如有不清楚的地方或者可以继续优化的地方,欢迎在下方留言探讨哦。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 浅显易懂,轻松搞定OSS的签名直传头像功能