本文主要介绍如何基于Post Policy的使用规则在服务端通过各种语言代码完成签名,并且设置上传回调,然后通过表单直传数据到OSS。
背景信息
大多数情况下,用户上传文件后,应用服务器需要知道用户上传了哪些文件以及文件名;如果上传了图片,还需要知道图片的大小等,为此OSS提供了上传回调方案。
流程介绍

当用户要上传一个文件到OSS,而且希望将上传的结果返回给应用服务器时,需要设置一个回调函数,将请求告知应用服务器。用户上传完文件后,不会直接得到返回结果,而是先通知应用服务器,再把结果转达给用户。
操作示例
流程解析
以下根据流程讲解核心代码和消息内容。
客户端源码解析
以下为常见功能的代码示例:
- 设置成随机文件名
若上传时采用固定格式的随机文件名,且后缀跟客户端文件名保持一致,可以将函数改为:
function check_object_radio() { g_object_name_type = 'random_name'; }
- 设置成用户的文件名
如果想在上传时设置成用户的文件名,可以将函数改为:
function check_object_radio() { g_object_name_type = 'local_name'; }
- 设置上传目录
上传的目录由服务端指定, 每个客户端只能上传到指定的目录,实现安全隔离。下面的代码以PHP为例,将上传目录改成abc/,注意目录必须以正斜线(/)结尾。
$dir ='abc/';
- 设置上传过滤条件
您可以利用Plupload的属性filters设置上传的过滤条件,如设置只能上传图片、上传文件的大小、不能有重复上传等。
var uploader = new plupload.Uploader({ …… filters: { mime_types : [ // 只允许上传图片和ZIP文件。 { title : "Image files", extensions : "jpg,gif,png,bmp" }, { title : "Zip files", extensions : "zip" } ], // 最大只能上传400KB的文件。 max_file_size : '400kb', // 不允许选取重复文件。 prevent_duplicates : true },
- mime_types:限制上传的文件后缀。
- max_file_size:限制上传的文件大小。
- prevent_duplicates:限制不能重复上传。
- 获取上传后的文件名
如果要知道文件上传成功后的文件名,可以用Plupload调用FileUploaded事件获取,如下所示:
FileUploaded: function(up, file, info) { if (info.status == 200) { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = 'upload to oss success, object name:' + get_uploaded_object_name(file.name); } else { document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = info.response; } }
可以利用
get_uploaded_object_name(file.name)
函数,得到上传到OSS的文件名,其中file.name
记录了本地文件上传的名称。 - 上传签名
JavaScript可以从服务端获取policyBase64、accessid、signature这三个变量,核心代码如下:
function get_signature() { // 判断expire的值是否超过了当前时间,如果超过了当前时间,则重新获取签名,缓冲时间为3秒。 now = timestamp = Date.parse(new Date()) / 1000; if (expire < now + 3) { body = send_request() var obj = eval ("(" + body + ")"); host = obj['host'] policyBase64 = obj['policy'] accessid = obj['accessid'] signature = obj['signature'] expire = parseInt(obj['expire']) callbackbody = obj['callback'] key = obj['dir'] return true; } return false; };
从服务端返回的消息解析如下:
说明 以下仅为示例,并不要求相同的格式,但必须包含accessid、policy、signature三个值。{"accessid":"LTAI5tAzivUnv4ZF1azP****", "host":"http://post-test.oss-cn-hangzhou.aliyuncs.com", "policy":"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wNVQyMDoyMzoyM1oiLCJjxb25kaXRpb25zIjpbWyJjcb250ZW50LWxlbmd0aC1yYW5nZSIsMCwxMDQ4NTc2MDAwXSxbInN0YXJ0cy13aXRoIiwiJGtleSIsInVzZXItZGlyXC8i****", "signature":"I2u57FWjTKqX/AE6doIdyff1****", "expire":1446726203,"dir":"user-dir/"}
- accessid:用户请求的accessid。
- host:用户要往哪个域名发送上传请求。
- policy:用户表单上传的策略(Policy),是经过Base64编码过的字符串。详情请参见Post Policy。
- signature:对Policy签名后的字符串。
- expire:上传策略Policy失效时间,在服务端指定。失效时间之前都可以利用此Policy上传文件,无需每次上传都去服务端获取签名。
说明 为了减少服务端的压力,初始化上传时,每上传一个文件,获取一次签名。再次上传文件时,对当前时间与签名时间进行比较,并查看签名时间是否失效。如果签名已失效,则重新获取一次签名,如果签名未失效,则使用之前的签名。解析Policy的内容如下:
{"expiration":"2015-11-05T20:23:23Z", "conditions":[["content-length-range",0,1048576000],// 上传文件的大小限制默认为5 GB。您可以自定义上传文件的大小限制。如果超过此限制,文件上传到OSS会报错。 ["starts-with","$key","user-dir/"]]
上面Policy中增加了starts-with,用来指定此次上传的文件名必须以user-dir开头,用户也可以自行指定。增加starts-with的原因是,在众多场景下,一个应用对应一个Bucket。为了防止数据覆盖,用户上传到OSS的每个文件都可以有特定的前缀。但这样存在一个问题,用户获取到这个Policy后,在失效期内都能修改上传前缀,从而上传到其他用户的目录下。为解决该问题,可在应用服务器端指定用户上传文件的前缀。这样即便用户获取了Policy也没有办法上传到其他用户的目录,从而保证了数据的安全性。
- 设置应用服务器的地址
在客户端源码
upload.js
文件中,如下代码片段的变量serverUrl
的值可以用来设置应用服务器的URL,设置完成后,客户端会向该serverUrl
发送Get请求来获取信息。// serverUrl是用户获取签名和Policy等信息的应用服务器的URL,请将下面的IP和Port配置为您自己的真实信息。 serverUrl = 'http://88.88.88.88:8888'
常见问题
前端如何实现批量上传文件?
OSS没有开放批量上传接口,如果需要批量上传,您可以使用一个循环去上传所有文件,示例与上传单个文件一致。