Commit ad17753418f454ec63a00d2647e073967c54d587
0 parents
Exists in
master
OSS from Aliyun
Showing 11 changed files with 4835 additions and 0 deletions Side-by-side Diff
.gitignore
OSS_Python_SDK.pdf
No preview for this file type
README
... | ... | @@ -0,0 +1,326 @@ |
1 | +阿里云开放存储服务 Open Storage Service (OSS) Python SDK说明文档 | |
2 | +=============================================================== | |
3 | +阿里云开放存储服务官方网站: | |
4 | + http://oss.aliyun.com | |
5 | + | |
6 | +阿里云开放存储 | |
7 | +=============================================================== | |
8 | +存储在OSS里的文件叫做"object". 所有的object都放在bucket里面。 | |
9 | + | |
10 | +简介 | |
11 | +=============================================================== | |
12 | +这篇文档主要介绍如何使用Python来进行OSS API调用,并且介绍osscmd | |
13 | +的简单使用。 | |
14 | +这篇文档假设你已经熟悉Python,熟悉OSS的相关概念,并且已经注册了 | |
15 | +阿里云的OSS服务,且获得了相应的ID和KEY。 | |
16 | +如果你还没有开通或者还不了解OSS,请移步OSS官方网站。 | |
17 | + | |
18 | +环境要求 | |
19 | +=============================================================== | |
20 | +Python SDK需要:安装python 2.5(包括)以上且在3.0(不包括)以下 | |
21 | +的版本。 | |
22 | +可以在Windows平台和Linux平台使用。 | |
23 | + | |
24 | +如何获取 | |
25 | +=============================================================== | |
26 | +1. 打开浏览器,输入oss.aliyun.com | |
27 | +2. 找到Python SDK链接: | |
28 | +3. 下载后可以得到类似OSS_Python_API_xxxxxxxx.tar.gz的包 | |
29 | +4. 进入压缩包所在的目录,进行解压缩 | |
30 | +5. 解压缩后得到,oss文件夹和osscmd文件 | |
31 | + | |
32 | +使用说明 | |
33 | +=============================================================== | |
34 | +使用oss_api.py | |
35 | +=============================================================== | |
36 | +1. 创建bucket | |
37 | + def put_bucket(self, bucket, acl='', headers=None): | |
38 | + 等同create_bucket函数 | |
39 | + def create_bucket(self, bucket, acl='', headers=None): | |
40 | + 参数说明: | |
41 | + bucket,类型:string | |
42 | + acl,类型:string,目前为private,public-read, | |
43 | + public-read-write中的一种 | |
44 | + headers, 类型:dict,默认为空 | |
45 | + 返回值说明: | |
46 | + HTTP Response | |
47 | + 参见http://docs.python.org/2/library/httplib.html | |
48 | + def put_bucket_with_location(self, bucket, acl='', \ | |
49 | + location='', headers=None): | |
50 | + 参数说明: | |
51 | + bucket,类型:string | |
52 | + acl,类型:string | |
53 | + location, 类型:string | |
54 | + headers, 类型:dict | |
55 | + 返回值说明: | |
56 | + HTTP Response | |
57 | +2. 删除bucket | |
58 | + def delete_bucket(self, bucket, headers=None): | |
59 | + 参数说明: | |
60 | + bucket,类型:string | |
61 | + headers, 类型:dict | |
62 | + 返回值说明: | |
63 | + HTTP Response | |
64 | +3. 修改bucket访问权限 | |
65 | + def put_bucket(self, bucket, acl='', headers=None): | |
66 | + def create_bucket(self, bucket, acl='', headers=None): | |
67 | + 同1中的put_bucket和create_bucket | |
68 | +4. 获取bucket访问权限 | |
69 | + def get_bucket_acl(self, bucket): | |
70 | + 参数说明: | |
71 | + bucket,类型:string | |
72 | + 返回值说明: | |
73 | + HTTP Response | |
74 | +5. 显示创建的bucket | |
75 | + def get_service(self, headers=None): | |
76 | + 参数说明: | |
77 | + headers, 类型:dict | |
78 | + 返回值说明: | |
79 | + HTTP Response | |
80 | + def list_all_my_buckets(self, headers=None): | |
81 | + 参数说明: | |
82 | + headers, 类型:dict | |
83 | + 返回值说明: | |
84 | + HTTP Response | |
85 | +6. 上传object | |
86 | + def put_object_from_string(self, bucket, object,\ | |
87 | + input_content,\ | |
88 | + content_type=DefaultContentType,\ | |
89 | + headers=None, params=None): | |
90 | + 参数说明: | |
91 | + bucket,类型:string | |
92 | + object,类型:string | |
93 | + input_content,类型:string | |
94 | + content_type,类型:string | |
95 | + headers,类型:dict | |
96 | + params,类型:dict | |
97 | + 返回值说明: | |
98 | + HTTP Response | |
99 | + def put_object_from_file(self, bucket, object,\ | |
100 | + filename, content_type='',\ | |
101 | + headers=None, params=None): | |
102 | + 参数说明: | |
103 | + bucket,类型:string | |
104 | + object,类型:string | |
105 | + filename,类型:string,本地需要上传的文件名 | |
106 | + content_type,类型:string,object的类型 | |
107 | + headers,类型:dict | |
108 | + params,类型:dict | |
109 | + 返回值说明: | |
110 | + HTTP Response | |
111 | +7. 显示上传的object | |
112 | + def get_bucket(self, bucket, prefix='', marker='',\ | |
113 | + delimiter='', maxkeys='', headers=None): | |
114 | + 同list_bucket | |
115 | + def list_bucket(self, bucket, prefix='', marker='',\ | |
116 | + delimiter='', maxkeys='', headers=None): | |
117 | + 参数说明: | |
118 | + bucket,类型:string | |
119 | + prefix,类型:string | |
120 | + marker,类型:string | |
121 | + delimiter,类型:string | |
122 | + maxkeys,类型:string | |
123 | + headers,类型:dict | |
124 | + 返回值说明: | |
125 | + HTTP Response | |
126 | +8. 删除object | |
127 | + def delete_object(self, bucket, object, headers=None): | |
128 | + 参数说明: | |
129 | + bucket,类型:string | |
130 | + object,类型:string | |
131 | + headers,类型:dict | |
132 | + 返回值说明: | |
133 | + HTTP Response | |
134 | +9. 下载object | |
135 | + def get_object_to_file(self, bucket, object,\ | |
136 | + filename, headers=None): | |
137 | + 参数说明: | |
138 | + bucket,类型:string | |
139 | + object,类型:string | |
140 | + filename,类型:string, | |
141 | + 将object内容下载到本地文件的文件名 | |
142 | + headers,类型:dict | |
143 | + 返回值说明: | |
144 | + HTTP Response | |
145 | +10. 使用示例: | |
146 | +在解压的oss目录下,创建一个测试文件test.py内容如下, | |
147 | +并将ACCESS_ID和SECRET_ACCESS_KEY的内容填写正确, | |
148 | +并且将BUCKET填写一个唯一的名字。 | |
149 | + | |
150 | +#!/usr/bin/env python | |
151 | +#coding=utf8 | |
152 | +import time | |
153 | +from oss_api import * | |
154 | +from oss_xml_handler import * | |
155 | +HOST="oss.aliyuncs.com" | |
156 | +ACCESS_ID = "" | |
157 | +SECRET_ACCESS_KEY = "" | |
158 | +#ACCESS_ID and SECRET_ACCESS_KEY 默认是空, | |
159 | +#请填入您申请的正确的ID和KEY. | |
160 | +BUCKET = "" | |
161 | +#bucket 默认是空,请填入唯一的bucket名称 | |
162 | +#例如test-bucket-20130101等带唯一日期的bucket名字. | |
163 | + | |
164 | +def check_not_empty(input, msg=""): | |
165 | + if not input: | |
166 | + print "Please make sure %s not empty!" % msg | |
167 | + exit(-1) | |
168 | +def check_res(res, msg=""): | |
169 | + if res.status / 100 == 2: | |
170 | + print "%s OK" % msg | |
171 | + else: | |
172 | + print "%s FAIL" % msg | |
173 | + print "ret:%s" % res.status | |
174 | + print "request-id:%s" % res.getheader("x-oss-request-id") | |
175 | + print "reason:%s" % res.read() | |
176 | + exit(-1) | |
177 | + | |
178 | +if __name__ == "__main__": | |
179 | + #初始化 | |
180 | + check_not_empty(ACCESS_ID, "ACCESS_ID") | |
181 | + check_not_empty(SECRET_ACCESS_KEY, "SECRET_ACCESS_KEY") | |
182 | + oss = OssAPI(HOST, ACCESS_ID, SECRET_ACCESS_KEY) | |
183 | + #创建属于自己的bucket | |
184 | + bucket = BUCKET | |
185 | + check_not_empty(bucket, "bucket") | |
186 | + acl = 'private' | |
187 | + headers = {} | |
188 | + res = oss.put_bucket(bucket, acl, headers) | |
189 | + check_res(res, "create bucket") | |
190 | + | |
191 | + #列出创建的bucket | |
192 | + res = oss.get_service() | |
193 | + check_res(res, "list all buckets") | |
194 | + #把指定的字符串内容上传到bucket中,在bucket中的文件名叫object。 | |
195 | + object = "object_test" | |
196 | + input_content = "hello, OSS" | |
197 | + content_type = "text/HTML" | |
198 | + headers = {} | |
199 | + res = oss.put_object_from_string(bucket, object, input_content, content_type, headers) | |
200 | + check_res(res, "upload from string") | |
201 | + #指定文件名, 把这个文件上传到bucket中,在bucket中的文件名叫object。 | |
202 | + object = "object_test" | |
203 | + filename = __file__ | |
204 | + content_type = "text/HTML" | |
205 | + headers = {} | |
206 | + res = oss.put_object_from_file(bucket, object, filename, content_type, headers) | |
207 | + check_res(res, "upload from localfile") | |
208 | + #下载bucket中的object,内容在body中 | |
209 | + object = "object_test" | |
210 | + headers = {} | |
211 | + res = oss.get_object(bucket, object, headers) | |
212 | + check_res(res, "download object") | |
213 | + #下载bucket中的object,把内容写入到本地文件中 | |
214 | + object = "object_test" | |
215 | + headers = {} | |
216 | + filename = "get_object_test_file" | |
217 | + res = oss.get_object_to_file(bucket, object, filename, headers) | |
218 | + if os.path.isfile(filename): | |
219 | + os.remove(filename) | |
220 | + check_res(res, "download object to localfile") | |
221 | + #查看bucket中所拥有的权限 | |
222 | + res = oss.get_bucket_acl(bucket) | |
223 | + check_res(res, "get bucket acl") | |
224 | + #列出bucket中所拥有的object | |
225 | + prefix = "" | |
226 | + marker = "" | |
227 | + delimiter = "/" | |
228 | + maxkeys = "100" | |
229 | + headers = {} | |
230 | + res = oss.get_bucket(bucket, prefix, marker, delimiter, maxkeys, headers) | |
231 | + check_res(res, "list objects in bucket") | |
232 | + #删除bucket中的object | |
233 | + object = "object_test" | |
234 | + headers = {} | |
235 | + res = oss.delete_object(bucket, object, headers) | |
236 | + check_res(res, "delete object") | |
237 | + #删除bucket | |
238 | + res = oss.delete_bucket(bucket) | |
239 | + check_res(res, "delete bucket") | |
240 | + | |
241 | +11. 示例的预期结果: | |
242 | + create bucket OK | |
243 | + list all buckets OK | |
244 | + upload from string OK | |
245 | + upload from localfile OK | |
246 | + download object OK | |
247 | + download object to localfile OK | |
248 | + get bucket acl OK | |
249 | + list objects in bucket OK | |
250 | + delete object OK | |
251 | + delete bucket OK | |
252 | + | |
253 | +使用osscmd | |
254 | +=============================================================== | |
255 | +1. 在Linux上安装 osscmd. | |
256 | + sudo rm -r /usr/local/oss | |
257 | + sudo mkdir -p /usr/local/oss | |
258 | + sudo tar -zxf oss.tar.gz -C /usr/local/oss | |
259 | + sudo rm -f /usr/bin/osscmd | |
260 | + sudo ln -s /usr/local/oss/osscmd /usr/bin/osscmd | |
261 | + sudo chmod 755 /usr/local/oss/osscmd | |
262 | + | |
263 | + 在Windows上安装osscmd | |
264 | + 解压缩包 | |
265 | + | |
266 | +2. 运行"python osscmd config --id=YOUR_ID --key=YOUR_KEY" | |
267 | + 用来配置访问OSS所需要的认证码 | |
268 | + | |
269 | + | |
270 | +3. 运行"python osscmd getallbucket" 列出创建的bucket. | |
271 | + 如果是刚刚使用OSS的用户因为没有创建bucket,输出是空 | |
272 | + | |
273 | +4. 运行"python osscmd createbucket mybucket" 创建一个名字 | |
274 | + 叫mybucket的bucket,有可能不成功,这个时候需要换一个名字。 | |
275 | + 因为OSS中的bucket名字是全局唯一的。 | |
276 | + | |
277 | +5. 可以再次运行"python osscmd getallbucket" 查看是否创建成功。 | |
278 | + 如果没有成功请检查osscmd返回的错误信息。 | |
279 | + | |
280 | +6. 成功创建bucket后。运行"python osscmd list oss://mybucket/", | |
281 | + 查看bucket中有哪些object。 | |
282 | + 由于bucket中还没有 | |
283 | + object,输出是空的。 | |
284 | + | |
285 | +7. 向bucket中上传一个object. | |
286 | + $ md5sum my_local_file | |
287 | + 7625e1adc3a4b129763d580ca0a78e44 my_local_file | |
288 | + | |
289 | + $ python osscmd put my_local_file oss://mybucket/myobject | |
290 | + | |
291 | +8. 如果创建成功,再次运行"python osscmd list oss://mybucket/" | |
292 | + | |
293 | +9. 从bucket中下载object到本地文件,并比对下载的文件的md5值 | |
294 | + $ python osscmd get oss://mybucket/myobject local_file | |
295 | + | |
296 | + $ md5sum local_file | |
297 | + 7625e1adc3a4b129763d580ca0a78e44 local_file | |
298 | + | |
299 | +10. 删除bucket中的object | |
300 | + $ python osscmd delete oss://mybucket/myobject | |
301 | + | |
302 | +11. 删除bucket, 注意,如果bucket中有object或者parts | |
303 | + 则这个bucket不能被删除 | |
304 | + $ python osscmd deletebucket test-oss-aliyun-com | |
305 | + | |
306 | +ChangeHistory | |
307 | +=============================================================== | |
308 | +0.3.2 - 2013-10-20 | |
309 | +* 修复osscmd的uploadfromdir命令中,在中文目录下,上传的object名字被截断的问题。 | |
310 | +* 修复oss_util.py中DEBUG被设置成True的情况下无法打印log的问题。 | |
311 | +* oss_api.py中增加了设置每次上传和下载大小的接口。 | |
312 | +* osscmd增加了--debug=true来打印日志。 | |
313 | +* oss_api.py中增加了上传失败时候的重试,最大重试100次。 | |
314 | + | |
315 | +0.3.1 - 2013-08-02 | |
316 | +* 支持跳转。 | |
317 | +* 给oss_api.py部分函数增加说明。 | |
318 | + | |
319 | +0.1.3 - 2013-07-12 | |
320 | +* 支持multipart相关操作,osscmd增加multipart相关的接口。 | |
321 | + osscmd支持本地目录上传。 | |
322 | + osscmd支持将bucket的某一个prefix的object下载到本地的目录。 | |
323 | + | |
324 | +0.1.0 - 2011-11-15 | |
325 | +* 第一次操作支持基本的创建,删除和显示bucket。 | |
326 | + 支持创建,删除和显示object。 |
oss/oss_api.py
Diff suppressed. Click to show
... | ... | @@ -0,0 +1,1497 @@ |
1 | +#!/usr/bin/env python | |
2 | +#coding=utf-8 | |
3 | + | |
4 | +# Copyright (c) 2011, Alibaba Cloud Computing | |
5 | +# All rights reserved. | |
6 | +# | |
7 | +# Permission is hereby granted, free of charge, to any person obtaining a | |
8 | +# copy of this software and associated documentation files (the | |
9 | +# "Software"), to deal in the Software without restriction, including | |
10 | +# without limitation the rights to use, copy, modify, merge, publish, dis- | |
11 | +# tribute, sublicense, and/or sell copies of the Software, and to permit | |
12 | +# persons to whom the Software is furnished to do so, subject to the fol- | |
13 | +# lowing conditions: | |
14 | +# | |
15 | +# The above copyright notice and this permission notice shall be included | |
16 | +# in all copies or substantial portions of the Software. | |
17 | +# | |
18 | +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
19 | +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
20 | +# ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
21 | +# SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
22 | +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
23 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
24 | +# IN THE SOFTWARE. | |
25 | + | |
26 | +import httplib | |
27 | +import time | |
28 | +import base64 | |
29 | +import urllib | |
30 | +import StringIO | |
31 | +import sys | |
32 | +try: | |
33 | + from oss.oss_util import * | |
34 | +except: | |
35 | + from oss_util import * | |
36 | +try: | |
37 | + from oss.oss_xml_handler import * | |
38 | +except: | |
39 | + from oss_xml_handler import * | |
40 | + | |
41 | +class OssAPI: | |
42 | + ''' | |
43 | + A simple OSS API | |
44 | + ''' | |
45 | + DefaultContentType = 'application/octet-stream' | |
46 | + provider = PROVIDER | |
47 | + __version__ = '0.3.2' | |
48 | + Version = __version__ | |
49 | + AGENT = 'oss-python%s (%s)' % (__version__, sys.platform) | |
50 | + | |
51 | + def __init__(self, host, access_id, secret_access_key='', port=80, is_security=False): | |
52 | + self.SendBufferSize = 8192 | |
53 | + self.RecvBufferSize = 1024*1024*10 | |
54 | + self.host = get_second_level_domain(host) | |
55 | + self.port = port | |
56 | + self.access_id = access_id | |
57 | + self.secret_access_key = secret_access_key | |
58 | + self.show_bar = False | |
59 | + self.is_security = is_security | |
60 | + self.retry_times = 5 | |
61 | + self.agent = self.AGENT | |
62 | + self.debug = False | |
63 | + | |
64 | + def set_debug(self, is_debug): | |
65 | + if is_debug: | |
66 | + self.debug = True | |
67 | + | |
68 | + def set_retry_times(self, retry_times=5): | |
69 | + self.retry_times = retry_times | |
70 | + | |
71 | + def set_send_buf_size(self, buf_size): | |
72 | + try: | |
73 | + self.SendBufferSize = (int)(buf_size) | |
74 | + except ValueError: | |
75 | + pass | |
76 | + | |
77 | + def set_recv_buf_size(self, buf_size): | |
78 | + try: | |
79 | + self.RecvBufferSize = (int)(buf_size) | |
80 | + except ValueError: | |
81 | + pass | |
82 | + | |
83 | + def get_connection(self, tmp_host=None): | |
84 | + host = '' | |
85 | + port = 80 | |
86 | + timeout = 10 | |
87 | + if not tmp_host: | |
88 | + tmp_host = self.host | |
89 | + host_port_list = tmp_host.split(":") | |
90 | + if len(host_port_list) == 1: | |
91 | + host = host_port_list[0].strip() | |
92 | + elif len(host_port_list) == 2: | |
93 | + host = host_port_list[0].strip() | |
94 | + port = int(host_port_list[1].strip()) | |
95 | + if self.is_security or port == 443: | |
96 | + self.is_security = True | |
97 | + if sys.version_info >= (2, 6): | |
98 | + return httplib.HTTPSConnection(host=host, port=port, timeout=timeout) | |
99 | + else: | |
100 | + return httplib.HTTPSConnection(host=host, port=port) | |
101 | + else: | |
102 | + if sys.version_info >= (2, 6): | |
103 | + return httplib.HTTPConnection(host=host, port=port, timeout=timeout) | |
104 | + else: | |
105 | + return httplib.HTTPConnection(host=host, port=port) | |
106 | + | |
107 | + def sign_url_auth_with_expire_time(self, method, url, headers=None, resource="/", timeout=60, params=None): | |
108 | + ''' | |
109 | + Create the authorization for OSS based on the input method, url, body and headers | |
110 | + | |
111 | + :type method: string | |
112 | + :param method: one of PUT, GET, DELETE, HEAD | |
113 | + | |
114 | + :type url: string | |
115 | + :param:HTTP address of bucket or object, eg: http://HOST/bucket/object | |
116 | + | |
117 | + :type headers: dict | |
118 | + :param: HTTP header | |
119 | + | |
120 | + :type resource: string | |
121 | + :param:path of bucket or object, eg: /bucket/ or /bucket/object | |
122 | + | |
123 | + :type timeout: int | |
124 | + :param | |
125 | + | |
126 | + Returns: | |
127 | + signature url. | |
128 | + ''' | |
129 | + if not headers: | |
130 | + headers = {} | |
131 | + if not params: | |
132 | + params = {} | |
133 | + send_time = str(int(time.time()) + timeout) | |
134 | + headers['Date'] = send_time | |
135 | + auth_value = get_assign(self.secret_access_key, method, headers, resource, None, self.debug) | |
136 | + params["OSSAccessKeyId"] = self.access_id | |
137 | + params["Expires"] = str(send_time) | |
138 | + params["Signature"] = auth_value | |
139 | + sign_url = append_param(url, params) | |
140 | + return sign_url | |
141 | + | |
142 | + def sign_url(self, method, bucket, object, timeout=60, headers=None, params=None): | |
143 | + ''' | |
144 | + Create the authorization for OSS based on the input method, url, body and headers | |
145 | + | |
146 | + :type method: string | |
147 | + :param method: one of PUT, GET, DELETE, HEAD | |
148 | + | |
149 | + :type bucket: string | |
150 | + :param: | |
151 | + | |
152 | + :type object: string | |
153 | + :param: | |
154 | + | |
155 | + :type timeout: int | |
156 | + :param | |
157 | + | |
158 | + :type headers: dict | |
159 | + :param: HTTP header | |
160 | + | |
161 | + :type params: dict | |
162 | + :param: the parameters that put in the url address as query string | |
163 | + | |
164 | + :type resource: string | |
165 | + :param:path of bucket or object, eg: /bucket/ or /bucket/object | |
166 | + | |
167 | + Returns: | |
168 | + signature url. | |
169 | + ''' | |
170 | + if not headers: | |