最近一直在跟S3打交道,但是苦于java不会,python懂一点,API这个东东经常听也知道是啥,但是没有实际根据API文档去进行相关开发的经历,所以前期一直很忐忑,都是找别人帮忙写好特定功能的程序,我只是使用而已,昨天呢一发狠,就试着将boto(python的S3库)的快速入门和API手册从头读起,收获颇丰,也瞬间揭开了API的神秘面纱,自此个也能自豪的说我也是用过API写过小程序的淫了啊。下面就是我针对我的应用场景根据S3的API整理的实现方式。
应用场景:需要存储东西到S3服务器上,每一个类别建一个特定名字的bucket,对于每一个类别分日期建立文件夹存储文件,要统计上传的进度。
解决方案:(python boto)
boto s3 API手册地址:/en/latest/ref/s3.html
boto s3 API 快速入门地址:/en/latest/s3_tut.html ——这里面讲到了的,我就略讲,主要是说点我不是很清楚的地方。
1.连接S3服务器,如果没有入门手册,连蒙带猜,也应该知道是在boto.s3.connection中,点开链接去看API手册,可以看到下面一行class boto.s3.connection.S3Connection(aws_access_key_id=None,aws_secret_access_key=None,
is_secure=True,port=None,proxy=None,proxy_port=None,proxy_user=None,proxy_pass=None,
host='',debug=0,https_connection_factory=None,
calling_format='boto.s3.connection.SubdomainCallingFormat',path='/',
provider='aws',bucket_class=,security_token=None,
suppress_consec_slashes=True,anon=False,validate_certs=None)
返回连接标示符
这个class开头的就是一个类啦,使用前记得import,或者直接将父类boto.s3.connection都给import了,里面的参数很多我也不知道是干啥的,但是aws_access_key_id,aws_secret_access_key是必须的,但是结合我的实际情况(我使用的是兼容S3接口)因此除了两个key外,host需要设置,还有is_secure=False,前辈写的oython连接脚本里面还有calling_format = boto.s3.connection.OrdinaryCallingFormat(),暂时不清楚是干啥的。
2.创建bucket,在API手册的boto.s3.connection部分继续往下翻,你能看到所有针对bucket的操作库,create_bucket(bucket_name, headers=None, location='', policy=None)
创建bucket,bucket名是必须的,如果是amazon的可以加location选择bucket放在哪。
delete_bucket(bucket, headers=None)
删除bucket,bucket名是必须的
get_all_buckets(headers=None)
获取所有bucket,放回一个列表,所有bucket名,和bucket的所有信息。
get_bucket(bucket_name,validate=True,headers=None)
获取指定bucket,默认validate为True返回改bucket的所有key即object。
3.新建文件夹,对于对象存储而言,没有文件夹的概念,所有的文件以及文件夹都看成是一个object,但是object前面可以有字符“/”来表示文件夹意义的标示符,因而本身s3是没有提供直接建文件夹的API的,但是利用前面的概念可以建一个结尾带有“/”的key,这个key的content为空,来象征性的标示文件夹,后续所谓的往这个文件夹里面继续存放东西就是在所有需要上传文件的文件名前面加上这个文件夹的key作为文件的key将文件上传,就是先所谓的文件夹的概念,在一些S3 client(如dragondisk)中,直接以目录结构显示S3里面的内容的时候会把“/”结尾的key以文件夹的形式展示。==========言而总是文件夹是通过创建名字尾为“/”,内容为空的key来实现的。
因此找到s3.boto.key由下面的API手册说明可知,要建立key,bucket名是必须的,还要通过s3.boto.key类下的诸多函数设置key的内容,内容来源可以string或者文件
boto.s3.key.Key(bucket=None,name=None) Represents a key (object) in an S3 bucket.Variables:name– The name of this Keyobject.
metadata– A dictionary containing user metadata that you wish to store with theobjector that has been retrieved from an existingobject.
cache_control– The value of the
associated with thisobject.
last_modified– The string timestamp representing the last time thisobjectwas modified in S3.
owner– The ID of the owner of thisobject.
storage_class– The storage class of theobject. Currently, one of: STANDARD | REDUCED_REDUNDANCY | GLACIER
md5– The MD5 hash of the contents of theobject.
size– The size, in bytes, of theobject.
version_id– The version ID of thisobject, if it is a versionedobject.
encrypted– Whether theobjectis encrypted while at rest on the server.
这个表也同时展示了一个key所具有的的所有属性,后续如果需要可以直接获取通过key.name样式获取
关于key的操作,以下函数用的也是比较多的,set_acl(acl_str,headers=None)
设置权限,权限有public-read,private等
set_contents_from_file(fp,headers=None,replace=True,cb=None,num_cb=10,policy=None,md5=None,reduced_redundancy=False,query_args=None,encrypt_key=False,size=None,rewind=False)
已经打开的文件中获取
set_contents_from_filename(filename,headers=None,replace=True,cb=None,num_cb=10,policy=None,md5=None,reduced_redundancy=False,,encrypt_key=False)
从指定文件获取,即将这个文件上传
set_contents_from_stream(fp,headers=None,replace=True,cb=None,num_cb=10,policy=None,reduced_redundancy=False,query_args=None,size=None)
从流中获取,这个是设置多线程上传的
set_contents_from_string(s,headers=None,replace=True,cb=None,num_cb=10,policy=None,md5=None,reduced_redundancy=False,encrypt_key=False)
从字符串获取,新建文件夹就用这个,字符串设置为空
上面是设置,下面的是获取,基本是一一对应的:get_acl(headers=None)
get_contents_as_string(headers=None,cb=None,num_cb=10,torrent=False,version_id=None,response_headers=None)
get_contents_to_file(fp,headers=None,cb=None,num_cb=10,torrent=False,version_id=None,res_download_handler=None,response_headers=None)
get_contents_to_filename(filename,headers=None,cb=None,num_cb=10,torrent=False,version_id=None,res_download_handler=None,response_headers=None)
get_file(fp,headers=None,cb=None,num_cb=10,torrent=False,version_id=None,override_num_retries=None,response_headers=None)
4.统计上传进度,这个是进行大批量文件上传的时候的一个大概的展示完成百分比,实现的方式思路也是很简单的,获取本地目录的大小,获取已上传的文件的大小,二者一比较就OK。但是问题是,一旦s3服务器上指定bucket下面有成千上网个文件,你要找到你这个过程上传的文件就不是一件轻松的事情了,当然s3在存储文件的key,前面讲到过,对于相同目录下面的文件,key的前面一段表示文件夹的那一部分名字是一样的,因此如果能够快速定位到前面表示文件夹名的那些key,就能够快速获得所有的文件,再回头看API手册的目录,我找到了
bucket名是必须的,prefix后面接你要筛选的文件夹名,可以有多级 如, test1/test2/test3/
统计文件大小的时候这里要说明一下,在linux上,默认呢会将所有文件夹的大小也算上,也就是所有文件的实际大小之和加上所有文件夹包含根文件夹的大小,每个文件夹是4096 bit。
==================================================================
整理一下前面所有脚本分段展示如下:##========1.连接s3服务器============================##
import boto
import boto.s3.connection
access_key = 'FA8LIWY0W7FOOL32FD7A'
secret_key = 'YWkILOIZYJRd4prIZwga5Hj5JB512cmdHEUc7o0I'
conn = boto.connect_s3(
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
host = '10.1.9.126',
is_secure=False, # uncommmnt if you are not using ssl
calling_format = boto.s3.connection.OrdinaryCallingFormat(),)
##========2.创建bucket,并回显所有bucket========================##
bucket = conn.create_bucket('test')
for bucket in conn.get_all_buckets():
print "{name}\t{created}".format(
name = bucket.name,
created = bucket.creation_date,
)
##=======3.创建文件夹======================##
from boto.s3.key import Key
k = Key(bucket)
k.key = 'testdir/'
k.set_contents_from_string('')
##======4.统计指定文件夹下所有文件大小,将文件夹大小考虑进去=======##
from boto.s3.bucketlistresultset import *
total=4096
for key in bucket_lister(bucket,prefix='s3test1-1108000001-0/client-installer'):
total +=key.size
if key.name[-1]=='/':
total +=4096
print total