S3常见接口使用

S3常见接口使用

分段上传

分段上传允许上传单个对象作为一组分段。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败,可以重新传输该分段且不会影响其他分段。当对象的所有段都上传后,Amazon S3 将这些段汇聚起来,然后创建对象。
分段上传可提供以下优势:

  • 文件小于5MB不适用分块上传
  • 并行上传分段以提高吞吐量。
  • 较小的分段大小可以将由于网络错误而需重启失败的上传所产生的影响降至最低。
  • 可以随时上传对象分段。启动分段上传后,不存在过期期限;您必须显式地完成或中止分段上传。
  • 可以在创建对象的同时上传对象。

分段上传分三个步骤:初始化准备、并行上传,完成上传。同时在并行阶段,还可以进行终止上传和查询已上传列表的操作。

上传初始化阶段

发送HTTP POST请求,成功则返回对应的upload ID(后续的上传操作都必须使用相同的upload ID),完成Metadata设置和ACL设置。

上传分段阶段

client端完成文件切片,每个片有一个1~10000之间的任意分段编号(相同的编号会出现覆盖),无论何时上传分段,Amazon S3 都将在其响应中返回ETag 标头。对于每个分段上传,必须记录分段编号和ETag 值。除最后一个分块以为,其余分块大于 5 MB。

完成上传阶段

完成分段上传时,Amazon S3 通过按升序的分段编号规范化分段来创建数据元。成功完成请求后,分段将不再存在。完成分段上传请求必须包括上传 ID 以及分段编号和相应的 ETag 值的列表。这一阶段在完成所有upload Part以后必须执行(否则占用的临时资源仍然纳入计费范围)

分段上传列表

对于每个列出分段请求,Amazon S3 将返回有关特定分段上传的分段信息,最多为 1 000 个分段。如果分段上传中的分段超过 1 000 个,您必须发送一系列列出分段请求以检索所有分段。返回的段列表不包括未完成上传的段

分块上传规范

名称 规范
最大对象大小 5 TB
每次上传的分段的最大数量 10000
分段编号 1 到 10000(含)
分段大小 5 MB 到 5 GB,最后一个分段可以 <5 MB
列出分段请求返回的分段的最大数量 1000
在列出分段上传请求中返回的分段的最大数量 1000

【代码示例】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# -*- coding: utf-8 -*-
import boto
import boto.s3.connection
import os
import boto.utils

# os.environ['S3_USE_SIGV4'] = 'True'

endpoint = 's3dev.nie.netease.com'
access_key = 'ELWZK6*****05YTC25'
secret_key = 'quDVDt*******eVvOQsP'

key_name = 'TCP-IP.pdf'
part_num = 2 # 文件切分数量
bucket_name = 'mybucket'
metadata={'Content-Type':'application/json','x-amz-meta-abc':'data'} #metadata定义
policy = 'public-read' # ACL配置
file_path = '/home/lihongbo01/workspace/s3_workspace/TCP-IP.pdf'

conn = boto.connect_s3(
aws_access_key_id = access_key,
aws_secret_access_key = secret_key,
host = endpoint,
is_secure=False,
calling_format = boto.s3.connection.SubdomainCallingFormat(),
)

# 定义一个函数完成本地文件的分块切片操作
def split_file(filename):
filelist=[]
statinfo = os.stat(filename)
chunksize = statinfo.st_size/part_num
print "file size: %d(mb)" % (statinfo.st_size/(1024*1024))
with open(filename, "rb") as f:
index = 1
while True:
chunk = f.read(chunksize)
if(chunk):
fn = "%s.part.%d" % (filename, index)
index = index + 1
filelist.append(fn)
print "creating", fn
with open(fn, "wb") as fw:
fw.write(chunk)
else:
break
return filelist

def up_with_multi_part(filename,bucketname,key_name,metadata=None,policy='private'):
bucket = conn.get_bucket(bucketname)
print bucket.get_location()
mpu = bucket.initiate_multipart_upload(key_name,metadata=metadata,policy=policy) # 初始化分块上传
print mpu.get_all_parts()
print mpu.id
filelist = split_file(filename)
f_num = 1
for f in filelist:
sfp = open(f,'rb')
hd, cm, cl = boto.utils.compute_md5(sfp)
md5 = (hd, cm)
print md5
mpu.upload_part_from_file(sfp, part_num=f_num,md5=md5) # 上传分块,每个分块都做md5校验
sfp.close()
f_num = f_num+1
print "%s is done" % f
mpu.complete_upload() # 完成上传
print "%s is done" % filename

up_with_multi_part(file_path, bucket_name, key_name,metadata,policy)

【效果】

1
2
3
4
5
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ ls
s3sdk.py split_upload.py TCP-IP.pdf TCP-IP.pdf.part.1 TCP-IP.pdf.part.2
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-17 06:29 19132008 s3://mybucket/TCP-IP.pdf
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py

【核心函数】

boto.connect_s3:连接S3
conn.get_bucket:根据name获取bucket
bucket.initiate_multipart_upload:初始化分段上传
boto.utils.compute_md5:计算文件md5值
mpu.upload_part_from_file:上传某一块
mpu.complete_upload():完成上传

【注意】

  1. 除最后一块外每块要大于5MB
  2. bucket要存在
  3. Debug可以根据接口返回的错误信息然后查阅API文档

对象批量删除

将多个对象的删除请求合成一个,降低请求的负载;批量删除之前需要获得这些待删除对象的key(最多一次1000个)。响应:verbose/quiet模式。

批量删除Object(Python版本)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# -*- coding: utf-8 -*-
from boto.s3.connection import S3Connection
import boto
import os

endpoint = 's3.ceph.work' #S3服务的endpoint地址
bucket_name = '' #bucket名称
access_key = '' #access-key
secret_key = '' #secret key

conn = boto.connect_s3(
aws_access_key_id=access_key,
aws_secret_access_key=secret_key,
host=endpoint,
is_secure=False,
calling_format=boto.s3.connection.SubdomainCallingFormat(),
validate_certs=True,
)

bucket = conn.get_bucket(bucket_name) #获取bucket实例
file_list = bucket.get_all_keys(prefix='user1_23695/') #按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录
bucket.delete_keys(file_list) #批量删除Object

【代码示例】

1
2
3
bucket = conn.get_bucket(bucket_name) # 获取bucket实例
file_list = bucket.get_all_keys(prefix='TCP') # 按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录
bucket.delete_keys(file_list) # 批量删除Object

【效果】

1
2
3
4
5
6
7
8
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-17 06:29 19132008 s3://mybucket/TCP-IP.pdf
2019-06-17 06:42 9566004 s3://mybucket/TCP-IP.pdf.part.1
2019-06-17 06:43 9566004 s3://mybucket/TCP-IP.pdf.part.2
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python batch_delete.py
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://mybucket
2019-06-14 09:38 1094 s3://mybucket/s3sdk.py

【核心函数】

bucket.delete_keys(file_list):批量删除Object

删除Buekct时先批量删除Object
1
2
3
4
5
6
7
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd rb s3://mybucket --force --recursive
WARNING: Bucket is not empty. Removing all the objects from it first. This may take some time...
delete: 's3://mybucket/in/mybucket/s3sdk.py'
delete: 's3://mybucket/s3sdk-in-mybucket.py'
Bucket 's3://mybucket/' removed
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ s3cmd ls s3://
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$

s3cmd rm s3://mybucket –recursive:清空桶(批量删除,支持前缀匹配)

获取对象列表

支持使用前缀

1
file_list = bucket.get_all_keys(prefix='user1_23695/')

【代码示例】

1
2
bucket = conn.get_bucket(bucket_name) #获取bucket实例
file_list = bucket.get_all_keys(prefix='TCP') #按指定prefix查询bucket中对应的Object列表,注意默认最多返回1000条记录

【效果】

1
2
3
4
5
6
7
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python list_key.py 
[<Key: mybucket,TCP-IP.pdf>, <Key: mybucket,TCP-IP.pdf.part.1>, <Key: mybucket,TCP-IP.pdf.part.2>]

## 带有目录包含着前缀(in)
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$ python list_key.py
[<Key: mybucket,in.py>, <Key: mybucket,in/s3sdk.py>]
lihongbo01@cld-unknown212867:~/workspace/s3_workspace$

返回的是一个ResultSet,接口可以参考:http://boto.cloudhackers.com/en/latest/ref/s3.html

【核心函数】

bucket.get_all_keys:获取所有键值