文件上传

在NOS中用户的基本操作单元是对象,亦可以理解为文件,NOS PYTHON SDK提供了丰富的上传接口,可以通过以下的方式上传文件:

  • 根据对象大小自动选择不同的上传方式
  • 字符串上传
  • 本地文件上传
  • 分片上传

字符串上传、本地文件上传最大为100M,分片上传对文件大小没有限制

根据对象大小自动选择不同的上传方式

您可以使用upload上传对象,upload会根据对象大小自动选择不同的上传方式,具体实现如下:

client.upload(
    bucket="使用的桶名,注意命名规则",
    key="使用的对象名,注意命名规则",
    body="对象内容,可以是文件句柄、字符串、字典等任何可序列化的对象",
    """
    * kwargs -- 其他可选参数。
        * meta_data(dict) -- 用户自定义的元数据,通过键值对的形式上报,键名和值均为字符串,且键名需以\`x-nos-meta-\`开头。
        * object_size(integer) -- 对象大小,默认通过body获取。
        * slice_size(integer) -- 分块大小,默认根据文件大小自动调整。
        * progress_callback(integer, integer) -- 上传进度回调函数,第一个参数是已经上传的文件大小(单位:byte),第二个参数是对象的总大小(单位:byte)
    """
    progress_callback=lambda x, y: {
        print('upload progress, uploaded_bytes:', x, ', total_bytes:', y)
    }
)

字符串上传

您可以使用put_object上传字符串内容到文件中,具体实现如下:

bucket = "使用的桶名,注意命名规则"
object = "使用的对象名,注意命名规则"
content = "Hello NOS!"

client.put_object(bucket, object, content)

Attention

1.上传的字符串内容不超过100M

本地文件上传

您可以使用put_object上传文件内容,具体实现如下:

bucket = "使用的桶名,注意命名规则"
object = "使用的对象名,注意命名规则"
file_name = "待上传文件的名称"

client.put_object(bucket, object, open(file_name, "rb"))

Attention

1.上传的文件内容不超过100M 2.必须以二进制的方式打开文件

分片上传

除了通过put_object接口上传文件到NOS之外,NOS还提供了另外一种上传模式-分片上传,用户可以在如下应用场景内(但不限于此),使用分片上传模式,如:

  • 需支持断点上传
  • 上传超过100M的文件
  • 网络条件较差,经常和NOS服务器断开连接
  • 上传文件之前无法确定文件的大小

原始接口分片上传

您可以使用原始的分片上传接口进行分片上传,一般流程如下所示:

  • 初始化一个分片上传任务(create_multipart_upload)
  • 逐个或并行上传分片(upload_part)
  • 完成分片上传(complete_multipart_upload)或者取消分片上传(abort_multipart_upload)

下面通过一个完整的示例说明了如何通过原始的api接口一步一步的进行分片上传操作,如果用户需要做断点续传等高级操作,可以参考下面代码:

bucket = "使用的桶名,注意命名规则"
object = "使用的对象名,注意命名规则"

# step 1. 初始化一个分块上传,获取分块上传ID,桶名 + 对像名 + 分块上传ID 唯一确定一个分块上传
result=client.create_multipart_upload(bucket, object)
# 分块上传ID用于后续分块上传操作
upload_id=result["response"].find("UploadId").text

# step 2. 上传分块
index = 0
slice_size = 100 * 1024 * 1024
file_name = "待上传文件的名称"
with open(file_name, "rb") as fp:
    while True:
        index += 1
        part = fp.read(slice_size)
        if not part:
            break
        client.upload_part(bucket, object, index, upload_id, part)

# step 3. 列出所有分块,完成分块上传
rParts = client.list_parts(bucket, object, upload_id)
Parts=rParts["response"]
partETags=[]
for k in Parts.findall("Part"):
    partETags.append({"part_num":k.find("PartNumber").text,"etag":k.find("ETag").text})

client.complete_multipart_upload(bucket, object, upload_id, partETags)

Attention

1.上面程序一共分为三个步骤:a. create_multipart_upload b.upload_part c. complete_multipart_upload
2.upload_part方法要求除最后一个Part以外,其他的Part大小都要大于或等于16K。但是upload_ part接口并不会立即校验上传Part的大小(因为不知道是否为最后一块),只有当complete_multipart_upload的时候才会校验。
3.Part号码的范围是1~10000。如果超出这个范围,NOS将返回InvalidArgument的错误码。
4.Part的大小为16K到100M
5.分片上传任务初始化或上传部分分片后,可以使用abort_multipart_ upload接口中止分片上传事件。当分片上传事件被中止后,就不能再使用这个upload_id做任何操作,已经上传的分片数据也会被删除。
6.在完成上传时,需要在参数中提供上传块的ETag与块编号(PartNumber)的组合信息,具体操作参考上面代码。

查看已经上传的分片

查看已经上传的分片可以罗列出指定upload_id(create_multipart_upload时获取)所属的所有已经上传成功的分片,您可以通过list_parts接口获取已经上传的分片,可以参考以下代码:

rParts = client.list_parts(bucket, object, upload_id)
for k in rParts.get("response").findall("Part"):
    print(k.find("PartNumber").text, k.find("ETag").text)

多分块上传

对于分块数量大于1000的分块上传情况,需要在list_parts时手动指定part的起始位置和数量,因为NOS list_parts每次最多允许list 1000条。 对于Python3 sdk可以参考以下的代码

part_number_marker = 0
partETags = []
for i in range(10):
    rParts = client.list_parts(bucket, object, upload_id, part_number_marker=part_number_marker, limit=1000)
    part_number_marker += 1000

    Parts = rParts["response"]
    for k in Parts.findall("Part"):
        part = k.find("PartNumber").text, k.find("ETag").text
        print(part)
        partETags.append({"part_num": k.find("PartNumber").text, "etag": k.find("ETag").text})
    if len(Parts.findall("Part")) < 1000:
        break