适用场景
指的是用户使用OSS API中的Post Object请求来完成Object的上传,上传的Object不能超过5GB。非常适合嵌入在HTML网页中来上传Object,比较常见的应用场景是网站应用,以招聘网站为例子:
上传限制
- 大小限制:使用表单上传时,Object不能超过5GB。
- 命名限制:使用UTF-8编码
- 长度必须在1-1023字节之间
- 不能以“/”或者“\”字符开头
使用表单上传的好处
- 从流程上,少了一步转发。
- 从架构上来说,原来的上传都统一走网站服务器,上传量过大时,瓶颈在网站服务器,可能需要扩容网站服务器。采用表单上传后,上传都是直接从客户端发送到OSS。上传量过大时,压力都在OSS上,由OSS来保障服务质量。
上传的安全及授权
为防止第三方未经授权向开发者的Bucket上传Object,OSS提供了Bucket和Object级别的访问权限控制,详细解释见OSS细粒度的权限控制。
为了授权给第三方上传,这里使用的是Post Policy的机制,详细见 PostObject。
使用表单上传的基本步骤
构建一个Post Policy。
Post请求的Policy表单域用于验证请求的合法性。例如可以指定上传的大小,可以指定上传的Object名字等,上传成功后客户端跳转到的URL,上传成功后客户端收到的状态码。具体请参考Post Policy。
例如如下Policy,网站用户能上传的过期时间是2115-01-27T10:56:19Z(这里为了测试成功写的过期时间很长,实际使用中不建议这样设置),能上传的文件最大为104857600字节。[backcolor=transparent] [backcolor=transparent]以[backcolor=transparent]Python[backcolor=transparent]代码为例子,[backcolor=transparent]Policy[backcolor=transparent]是[backcolor=transparent]json[backcolor=transparent]格式的字符串。- [backcolor=transparent] policy[backcolor=transparent]=[backcolor=transparent]"{\"expiration\":\"2115-01-27T10:56:19Z\",\"conditions\":[[\"content-length-range\", 0, 104857600]]}"
将Policy字符串进行base64编码。用OSS的AccessKeySecret对base64编码后的Policy进行签名。构建上传的HTML页面。打开HTML页面,选择文件上传。
完整Python代码示例:
- [backcolor=transparent]#coding=utf8
- [backcolor=transparent]import[backcolor=transparent] md5
- [backcolor=transparent]import[backcolor=transparent] hashlib
- [backcolor=transparent]import[backcolor=transparent] base64
- [backcolor=transparent]import[backcolor=transparent] hmac
- [backcolor=transparent]from[backcolor=transparent] optparse [backcolor=transparent]import[backcolor=transparent] [backcolor=transparent]OptionParser
- [backcolor=transparent]def[backcolor=transparent] convert_base64[backcolor=transparent]([backcolor=transparent]input[backcolor=transparent]):
- [backcolor=transparent] [backcolor=transparent]return[backcolor=transparent] base64[backcolor=transparent].[backcolor=transparent]b64encode[backcolor=transparent]([backcolor=transparent]input[backcolor=transparent])
- [backcolor=transparent]def[backcolor=transparent] get_sign_policy[backcolor=transparent]([backcolor=transparent]key[backcolor=transparent],[backcolor=transparent] policy[backcolor=transparent]):
- [backcolor=transparent] [backcolor=transparent]return[backcolor=transparent] base64[backcolor=transparent].[backcolor=transparent]b64encode[backcolor=transparent]([backcolor=transparent]hmac[backcolor=transparent].[backcolor=transparent]new[backcolor=transparent]([backcolor=transparent]key[backcolor=transparent],[backcolor=transparent] policy[backcolor=transparent],[backcolor=transparent] hashlib[backcolor=transparent].[backcolor=transparent]sha1[backcolor=transparent]).[backcolor=transparent]digest[backcolor=transparent]())
- [backcolor=transparent]def[backcolor=transparent] get_form[backcolor=transparent]([backcolor=transparent]bucket[backcolor=transparent],[backcolor=transparent] endpoint[backcolor=transparent],[backcolor=transparent] access_key_id[backcolor=transparent],[backcolor=transparent] access_key_secret[backcolor=transparent],[backcolor=transparent] out[backcolor=transparent]):
- [backcolor=transparent] [backcolor=transparent]#1 构建一个Post Policy
- [backcolor=transparent] policy[backcolor=transparent]=[backcolor=transparent]"{\"expiration\":\"2115-01-27T10:56:19Z\",\"conditions\":[[\"content-length-range\", 0, 1048576]]}"
- [backcolor=transparent] [backcolor=transparent]print[backcolor=transparent]([backcolor=transparent]"policy: %s"[backcolor=transparent] [backcolor=transparent]%[backcolor=transparent] policy[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]#2 将Policy字符串进行base64编码
- [backcolor=transparent] base64policy [backcolor=transparent]=[backcolor=transparent] convert_base64[backcolor=transparent]([backcolor=transparent]policy[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]print[backcolor=transparent]([backcolor=transparent]"base64_encode_policy: %s"[backcolor=transparent] [backcolor=transparent]%[backcolor=transparent] base64policy[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]#3 用OSS的AccessKeySecret对编码后的Policy进行签名
- [backcolor=transparent] signature [backcolor=transparent]=[backcolor=transparent] get_sign_policy[backcolor=transparent]([backcolor=transparent]access_key_secret[backcolor=transparent],[backcolor=transparent] base64policy[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]#4 构建上传的HTML页面
- [backcolor=transparent] form [backcolor=transparent]=[backcolor=transparent] [backcolor=transparent]'''
- [backcolor=transparent] <html>
- [backcolor=transparent] <meta http-equiv=content-type content="text/html; charset=UTF-8">
- [backcolor=transparent] <head><title>OSS表单上传(PostObject)</title></head>
- [backcolor=transparent] <body>
- [backcolor=transparent] <form action="http://%s.%s" method="post" enctype="multipart/form-data">
- [backcolor=transparent] <input type="text" name="OSSAccessKeyId" value="%s">
- [backcolor=transparent] <input type="text" name="policy" value="%s">
- [backcolor=transparent] <input type="text" name="Signature" value="%s">
- [backcolor=transparent] <input type="text" name="key" value="upload/${filename}">
- [backcolor=transparent] <input type="text" name="success_action_redirect" value="http://oss.aliyun.com">
- [backcolor=transparent] <input type="text" name="success_action_status" value="201">
- [backcolor=transparent] <input name="file" type="file" id="file">
- [backcolor=transparent] <input name="submit" value="Upload" type="submit">
- [backcolor=transparent] </form>
- [backcolor=transparent] </body>
- [backcolor=transparent] </html>
- [backcolor=transparent] '''[backcolor=transparent] [backcolor=transparent]%[backcolor=transparent] [backcolor=transparent]([backcolor=transparent]bucket[backcolor=transparent],[backcolor=transparent] endpoint[backcolor=transparent],[backcolor=transparent] access_key_id[backcolor=transparent],[backcolor=transparent] base64policy[backcolor=transparent],[backcolor=transparent] signature[backcolor=transparent])
- [backcolor=transparent] f [backcolor=transparent]=[backcolor=transparent] open[backcolor=transparent]([backcolor=transparent]out[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"wb"[backcolor=transparent])
- [backcolor=transparent] f[backcolor=transparent].[backcolor=transparent]write[backcolor=transparent]([backcolor=transparent]form[backcolor=transparent])
- [backcolor=transparent] f[backcolor=transparent].[backcolor=transparent]close[backcolor=transparent]()
- [backcolor=transparent] [backcolor=transparent]print[backcolor=transparent]([backcolor=transparent]"form is saved into %s"[backcolor=transparent] [backcolor=transparent]%[backcolor=transparent] out[backcolor=transparent])
- [backcolor=transparent]if[backcolor=transparent] __name__ [backcolor=transparent]==[backcolor=transparent] [backcolor=transparent]'__main__'[backcolor=transparent]:
- [backcolor=transparent] parser [backcolor=transparent]=[backcolor=transparent] [backcolor=transparent]OptionParser[backcolor=transparent]()
- [backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]add_option[backcolor=transparent]([backcolor=transparent]""[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"--bucket"[backcolor=transparent],[backcolor=transparent] dest[backcolor=transparent]=[backcolor=transparent]"bucket"[backcolor=transparent],[backcolor=transparent] help[backcolor=transparent]=[backcolor=transparent]"specify "[backcolor=transparent])
- [backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]add_option[backcolor=transparent]([backcolor=transparent]""[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"--endpoint"[backcolor=transparent],[backcolor=transparent] dest[backcolor=transparent]=[backcolor=transparent]"endpoint"[backcolor=transparent],[backcolor=transparent] help[backcolor=transparent]=[backcolor=transparent]"specify"[backcolor=transparent])
- [backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]add_option[backcolor=transparent]([backcolor=transparent]""[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"--id"[backcolor=transparent],[backcolor=transparent] dest[backcolor=transparent]=[backcolor=transparent]"id"[backcolor=transparent],[backcolor=transparent] help[backcolor=transparent]=[backcolor=transparent]"access_key_id"[backcolor=transparent])
- [backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]add_option[backcolor=transparent]([backcolor=transparent]""[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"--key"[backcolor=transparent],[backcolor=transparent] dest[backcolor=transparent]=[backcolor=transparent]"key"[backcolor=transparent],[backcolor=transparent] help[backcolor=transparent]=[backcolor=transparent]"access_key_secret"[backcolor=transparent])
- [backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]add_option[backcolor=transparent]([backcolor=transparent]""[backcolor=transparent],[backcolor=transparent] [backcolor=transparent]"--out"[backcolor=transparent],[backcolor=transparent] dest[backcolor=transparent]=[backcolor=transparent]"out"[backcolor=transparent],[backcolor=transparent] help[backcolor=transparent]=[backcolor=transparent]"out put form"[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]([backcolor=transparent]opts[backcolor=transparent],[backcolor=transparent] args[backcolor=transparent])[backcolor=transparent] [backcolor=transparent]=[backcolor=transparent] parser[backcolor=transparent].[backcolor=transparent]parse_args[backcolor=transparent]()
- [backcolor=transparent] [backcolor=transparent]if[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]bucket [backcolor=transparent]and[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]endpoint [backcolor=transparent]and[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]id [backcolor=transparent]and[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]key [backcolor=transparent]and[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]out[backcolor=transparent]:
- [backcolor=transparent] get_form[backcolor=transparent]([backcolor=transparent]opts[backcolor=transparent].[backcolor=transparent]bucket[backcolor=transparent],[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]endpoint[backcolor=transparent],[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]id[backcolor=transparent],[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]key[backcolor=transparent],[backcolor=transparent] opts[backcolor=transparent].[backcolor=transparent]out[backcolor=transparent])
- [backcolor=transparent] [backcolor=transparent]else[backcolor=transparent]:
- [backcolor=transparent] [backcolor=transparent]print[backcolor=transparent] [backcolor=transparent]"python %s --bucket=your-bucket --endpoint=oss-cn-hangzhou.aliyuncs.com --id=your-access-key-id --key=your-access-key-secret --out=out-put-form-name"[backcolor=transparent] [backcolor=transparent]%[backcolor=transparent] __file__
将此段代码保存为post_object.py,然后用python post_object.py来运行。
- [backcolor=transparent]用法:
- [backcolor=transparent]python post_object[backcolor=transparent].[backcolor=transparent]py [backcolor=transparent]--[backcolor=transparent]bucket[backcolor=transparent]=您的[backcolor=transparent]Bucket[backcolor=transparent] [backcolor=transparent]--[backcolor=transparent]endpoint[backcolor=transparent]=[backcolor=transparent]Bucket[backcolor=transparent]对应的[backcolor=transparent]OSS[backcolor=transparent]域名[backcolor=transparent] [backcolor=transparent]--[backcolor=transparent]id[backcolor=transparent]=您的[backcolor=transparent]AccessKeyId[backcolor=transparent] [backcolor=transparent]--[backcolor=transparent]key[backcolor=transparent]=您的[backcolor=transparent]AccessKeySecret[backcolor=transparent] [backcolor=transparent]--[backcolor=transparent]out[backcolor=transparent]=输出的文件名
- [backcolor=transparent]示例:
- [backcolor=transparent]python post_object[backcolor=transparent].[backcolor=transparent]py [backcolor=transparent]--[backcolor=transparent]bucket[backcolor=transparent]=[backcolor=transparent]oss[backcolor=transparent]-[backcolor=transparent]sample [backcolor=transparent]--[backcolor=transparent]endpoint[backcolor=transparent]=[backcolor=transparent]oss[backcolor=transparent]-[backcolor=transparent]cn[backcolor=transparent]-[backcolor=transparent]hangzhou[backcolor=transparent].[backcolor=transparent]aliyuncs[backcolor=transparent].[backcolor=transparent]com [backcolor=transparent]--[backcolor=transparent]id[backcolor=transparent]=[backcolor=transparent]tphpxp [backcolor=transparent]--[backcolor=transparent]key[backcolor=transparent]=[backcolor=transparent]ZQNJzf4QJRkrH4[backcolor=transparent] [backcolor=transparent]--[backcolor=transparent]out[backcolor=transparent]=[backcolor=transparent]post[backcolor=transparent].[backcolor=transparent]html
[backcolor=transparent]注意:
- 构建的表单中 success_action_redirect value=http://oss.aliyun.com 表示上传成功后跳转的页面。可以替换成您自己的页面。
- 构建的表单中success_action_status value=201表示的是上传成功后返回的状态码为201。可以替换。
- 假如指定生成的HTML文件为post.html,打开post.html,选择文件上传。在这个例子中如果成功则会跳转到OSS的主页面。
功能使用参考
最佳实践
相关参考链接