所有文档

          对象存储 BOS

          文件管理

          上传文件

          在BOS中,用户操作的基本数据单元是Object。Bucket中的Object数量不限,但单个Object最大允许存储5TB的数据。Object包含Key、Meta和Data。其中,Key是Object的名字;Meta是用户对该Object的描述,由一系列Name-Value对组成;Data是Object的数据。

          BOS Python SDK提供了丰富的文件上传接口,可以通过以下方式上传文件:

          • 简单上传
          • 追加上传
          • 分片上传
          • 断点续传上传

          Object的命名规范如下:

          • 使用UTF-8编码。
          • 长度必须在1-1023字节之间。
          • 首字母不能为'/',不能包含'@'字符,'@'用于图片处理接口。

          简单上传

          BOS在简单上传的场景中,支持以指定文件形式、以数据流方式、以字符串方式执行Object上传,请参考如下代码:

          1. 如下代码可以进行Object上传:

            data = open(file_name, 'rb')
            #以数据流形式上传Object,用户需要自行计算数据长度content_length
            #用户需自行计算content_md5.计算方法是对数据执行md5算法获取128位二进制数据,再进行base64编码
            bos_client.put_object(bucket_name, object_key, data, content_length,content_md5)
            
            #从字符串中上传的Object
            bos_client.put_object_from_string(bucket_name, object_key, string)
            
            #从文件中上传的Object
            bos_client.put_object_from_file(bucket_name, object_key, file_name)

          其中,data为流对象,不同类型的Object采用不同的处理方法,从字符串中的上传使用StringIO的返回,从文件中的上传使用open()的返回,因此BOS提供了封装好的接口方便用户进行快速上传。

          Object以文件的形式上传到BOS中,put_object相关接口均支持不超过5GB的Object上传。在put_object、put_object_from_string或者put_object_from_file请求处理成功后,BOS会在Header中返回Object的ETag作为文件标识。

          这些接口均有可选参数:

          参数 说明
          content_type 上传文件或字符串的类型
          content_md5 文件数据校验,设置后BOS会启用文件内容MD5校验,把您提供的MD5与文件的MD5比较,不一致会抛出错误
          content_length 定义文件长度,put_object_from_string()不包含该参数
          content_sha256 用于进行文件校验
          user_metadata 用户自定义元数据
          storage_class 设置文件存储类型
          user_headers 用户定义header

          content_md5计算方法是对数据执行md5算法获取128位二进制数据,再进行base64编码。示例如下:

          import io
          import hashlib
          import base64
          
          file_name = "your_file"
          buf_size = 8192
          fp = open(file_name, 'rb')
          md5 = hashlib.md5()
          while True:
              bytes_to_read = buf_size
              buf = fp.read(bytes_to_read)
              if not buf:
                  break
              md5.update(buf)
          content_md5 = base64.standard_b64encode(md5.digest())

          设置文件元信息

          文件元信息(Object Meta),是对用户在向BOS上传文件时,同时对文件进行的属性描述,主要分为分为两种:设置HTTP标准属性(HTTP Headers)和用户自定义的元信息。

          设定Object的Http Header BOS Python SDK本质上是调用后台的HTTP接口,因此用户可以在上传文件时自定义Object的Http Header。常用的http header说明如下:

          名称 描述 默认值
          Cache-Control 指定该Object被下载时的网页的缓存行为
          Content-Encoding 表示消息主体进行了何种方式的内容编码转换
          Content-Disposition 指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称
          Expires 缓存过期时间

          参考代码如下:

          • 从字符串中上传带有特定header的object

            user_headers = {"header_key":"header_value"}
            #从字符串中上传带有特定header的object
            bos_client.put_object_from_string(bucket=bucket_name, 
                                              key=object_key, 
                                              data=string,
                                              user_headers=user_headers)
            #从文件中上传带有特定header的object
            bos_client.put_object_from_file(bucket=bucket_name,
                                        key=object_key,
                                        file_name=file,
                                        user_headers=user_headers)

          用户自定义元信息

          BOS支持用户自定义元数据来对Object进行描述。如下代码所示:

           #用户自定义元数据
           user_metadata = {"name":"my-data"}
           #从字符串中上传带有用户自定义meta的object
           bos_client.put_object_from_string(bucket=bucket_name, 
                                             key=object_key, 
                                             data=string,
                                             user_metadata=user_metadata)
           #从文件中上传带有用户自定义meta的object
           bos_client.put_object_from_file(bucket=bucket_name,
                                       key=object_key,
                                       file_name=file,
                                       user_metadata=user_metadata)

          提示:

          • 在上面代码中,用户自定义了一个名字为”name”,值为”my-data”的元数据
          • 当用户下载此Object的时候,此元数据也可以一并得到
          • 一个Object可以有多个类似的参数,但所有的User Meta总大小不能超过2KB

          设置Object的Copy属性

          BOS同时会提供copy_object接口用于将一个已经存在的Object拷贝到另外一个Object,拷贝过程中会对源Object的Etag或修改状态进行判断,根据判断结果决定是否执行拷贝。详细的参数解释如下:

          名称 类型 描述 是否必需
          x-bce-copy-source-if-match String 如果源Object的ETag值和用户提供的ETag相等,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-none-match String 如果源Object的ETag和用户提供的ETag不相等,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-unmodified-since String 如果源object在x-bce-copy-source-if-unmodified-since之后没被修改,则执行拷贝操作,否则拷贝失败。
          x-bce-copy-source-if-modified-since String 如果源object在x-bce-copy-source-if-modified-since之后被修改了,则执行拷贝操作,否则拷贝失败。

          对应的示例代码:

          copy_object_user_headers = {"copy_header_key":"copy_header_value"}
          
          bos_client.copy_object(source_bucket_name = bucket_name, 
                                 source_key = object_name, 
                                 target_bucket_name = bucket_name, 
                                 target_key = object_name, 
                                 user_metadata = user_metadata,
                                 user_headers = user_headers,
                                 copy_object_user_headers = copy_object_user_headers)

          上传Object时设置存储类型

          BOS支持标准存储, 低频存储,冷存储和归档存储,上传Object并存储为某种存储类型时通过指定StorageClass实现,默认为标准存储,四种存储类型对应的参数如下:

          存储类型 参数
          标准存储 STANDARD
          低频存储 STANDARD_IA
          冷存储 COLD
          归档存储 ARCHIVE

          以低频存储和归档存储为例,代码如下:

           from baidubce.services.bos import storage_class
           #从文件中上传冷存储类型的Object
           bos_client.put_object_from_file(bucket=bucket_name,
                                         key=object_key,
                                         file_name=file,
                                         storage_class=storage_class.COLD)
           #从字符串上传冷存储类型的Object
           bos_client.put_object_from_string(bucket=bucket_name, 
                                           key=object_key, 
                                           data=string,
                                           storage_class=storage_class.COLD)
           #从文件中上传归档存储类型的Object
           bos_client.put_object_from_file(bucket=bucket_name,
                                         key=object_key,
                                         file_name=file,
                                         storage_class=storage_class.ARCHIVE)

          追加上传

          上文介绍的简单上传方式,创建的Object都是Normal类型,用户不可再进行追加写,这在日志、视频监控、视频直播等数据复写较频繁的场景中使用不方便。

          正因如此,百度智能云BOS支持AppendObject,即以追加写的方式上传文件。通过AppendObject操作创建的Object类型为Appendable Object,可以对该Object追加数据。AppendObject大小限制为0~5G。归档存储类型不支持追加上传。

          通过AppendObject方式上传示例代码如下:

           #上传appendable object。其中“content_md5(data)”表示需要用户自行计算上传数据的md5值。
           #content_md5计算方法是对数据执行md5算法获取128位二进制数据,再进行base64编码。示例见上文“简单上传”部分。
           #其中“content_length(data)”表示需要用户自行计算上传数据的长度
           response = bos_client.append_object(bucket_name=bucket_name, 
                                               key=object_key,
                                               data=data,
                                               content_md5=content_md5(data), content_length=content_length(data))
           #获取下次追加写的位置
           next_offset = response.metadata.bce_next_append_offset
           bos_client.append_object(bucket_name=bucket_name, 
                                    key=object_key,
                                    data=next_data,
                                    content_md5=content_md5(next_data), content_length=content_length(next_data),
                                    offset=next_offset)
          
           #从字符串上传appendable object
           from baidubce.services.bos import storage_class
           bos_client.append_object_from_string(bucket_name=bucket_name,
                                                key=object_key,
                                                data=string,
                                                offset=offset,
                                                storage_class=storage_class.STANDARD,
                                                user_headers=user_headers)

          分块上传

          除了通过putObject接口上传文件到BOS以外,BOS还提供了另外一种上传模式 —— Multipart Upload。用户可以在如下的应用场景内(但不仅限于此),使用Multipart Upload上传模式,如:

          • 需要支持断点上传。
          • 上传超过5GB大小的文件。
          • 网络条件较差,和BOS的服务器之间的连接经常断开。
          • 需要流式地上传文件。
          • 上传文件之前,无法确定上传文件的大小。

          下面将介绍分步实现Multipart Upload。

          初始化Multipart Upload

          BOS使用initiate_multipart_upload方法来初始化一个分块上传事件:

          upload_id = bos_client.initiate_multipart_upload(bucket_name, object_key).upload_id

          该方法会返回InitMultipartUploadResponse对象,此对象中包含uploadId参数,用来表示此次的上传事件。

          带有特定header的分块上传的初始化

          bos_client.initiate_multipart_upload(bucket_name=bucket, 
                                               key=object_key,
          									 user_headers=user_headers)

          其中,header可设置的属性有:"Cache-Control"、"Content-Encoding"、"Content-Disposition"、"Expires",get-object和get-object-meta两个接口会返回设置的这四个header。

          低频、冷存储、归档存储存储分块上传的初始化

          低频存储分块上传的初始化需要指定storage_class,请参考以下代码(冷存储以此类推):

          from baidubce.services.bos import storage_class
          
          bos_client.initiate_multipart_upload(bucket_name=bucket, 
                                                   key=object_key,
                                                   storage_class = storage_class.STANDARD_IA)

          上传分块

          初始化完成后,进行分块上传:

           left_size = os.path.getsize(file_name)
           # left_size用于设置分块开始位置
           # 设置分块的开始偏移位置
           offset = 0
          
           part_number = 1
           part_list = []
          
           while left_size > 0:
           	# 设置每块为5MB
               part_size = 5 * 1024 * 1024
               if left_size < part_size:
                   part_size = left_size
          
               response = bos_client.upload_part_from_file(
                   bucket_name, object_key, upload_id, part_number, part_size, file_name, offset)
          
          
               left_size -= part_size
               offset += part_size
               part_list.append({
                   "partNumber": part_number,
                   "eTag": response.metadata.etag
               })
          
               part_number += 1

          注意:

          1. offset参数以字节为单位,为分块的开始偏移位置。
          2. size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于5MB。但是Upload Part接口并不会立即校验上传Part的大小;只有当调用complete_multipart_upload()的时候才会校验。
          3. 为了保证数据在网络传输过程中不出现错误,建议您在Upload Part后,使用每个分块BOS返回的Content-MD5值分别验证已上传分块数据的正确性。当所有分块数据合成一个Object后,不再含MD5值。
          4. Part号码的范围是1~10000。如果超出这个范围,BOS将返回InvalidArguement的错误码。
          5. 每次上传Part时都要把流定位到此次上传块开头所对应的位置。
          6. 每次上传Part之后,BOS的返回结果会包含一个etag与块编号(partNumber),在后续完成分块上传的步骤中会用到它,因此需要将其保存起来。一般来讲这些 etag和partNumber将被保存到List中。

          完成分块上传

          bos_client.complete_multipart_upload(bucket_name, object_key, upload_id, part_list)

          其中,part_list类型是list,里面每个元素是个dict,每个dict包含两个关键字,一个是partNumber, 一个是eTag。

          示例如下:

          [{'partNumber': 1, 'eTag': 'f1c9645dbc14efddc7d8a322685f26eb'}, {'partNumber': 2, 'eTag': 'f1c9645dbc14efddc7d8a322685f26eb'}, {'partNumber': 3, 'eTag': '93b885adfe0da089cdf634904fd59f71'}]

          该方法返回的解析类中可供调用的参数有:

          参数 说明
          bucket Bucket名称
          key Object名称
          e_tag 每个上传分块的ETag
          location Object的URL

          注意:此对象中包含的ETag是上传分块过程中每个Part的ETag,BOS收到用户提交的Part列表后,会逐一验证每个数据Part的有效性。当所有的数据Part验证通过后,BOS将把这些数据part组合成一个完整的Object。

          取消分块上传事件

          用户可以使用abort_multipart_upload方法取消分块上传:

          bos_client.abort_multipart_upload(bucket_name, object_key, upload_id = upload_id)

          获取未完成的分块上传事件

          用户可以使用如下两种方法获取Bucket中未完成的分块上传事件:

          方法一:

          response = bos_client.list_multipart_uploads(bucket_name)
          for item in response.uploads:
          	print item.upload_id

          list_multipart_uploads每次BOS最多返回1000个Multipart Upload,BOS支持prefix和delimiter过滤。

          list_multipart_uploads方法可供调用的参数还有:

          名称 类型 描述 是否必需
          delimiter String 分隔符; 主要应此项实现list文件夹的逻辑
          key_marker String Object按照字典序排序后,本次从keyMarker的后面的一条开始返回
          max_uploads Int 本次请求返回Multipart Uploads的最大数目,默认1000,最大1000
          prefix String key前缀,限定返回的object key必须以此为前缀

          list_multipart_uploads方法返回的解析类中可供调用的参数有:

          参数 说明
          bucket Bucket名称
          key_marker 开始上传的分块Object名称
          next_key_marker 当指定了delimiter且IsTruncated true时,才返回此项,作为下次查询marker的值
          is_truncated 指明是否所有查询都返回了;false-本次已经返回所有结果,true-本次还没有返回所有结果
          prefix 匹配以prefix开始到第一次出现Delimiter字符之间的object作为一组元素返回
          common_prefixes 仅当指定delimiter,才会返回此项
          delimiter 查询的结束符
          max_uploads 请求返回的最大数目
          uploads 全部未完成的分快上传事件容器
          +owner 对应Bucket所属用户信息
          +id Bucket Owner的用户id
          +display_name Bucket Owner的名称
          +key 分块所属Object名称
          +upload_id 分块上传id
          +initiated 分块上传开始时间

          list_all_multipart_uploads方法返回uploads的生成器(Generator),并且不受单次最大返回1000个结果的限制,会返回所有的结果。

          方法二:

          uploads = list_all_multipart_uploads(bucket_name)
          for item in uploads:
              print item.upload_id

          获取所有已上传的块信息

          用户可以使用如下两种方法获取某个上传事件中所有已上传的块:

          方法一:

          response = bos_client.list_parts(bucket_name, object_key, upload_id)
          for item in response.parts:
              print  item.part_number

          注意:

          1. BOS按照PartNumber升序排序。
          2. 由于网络传输可能出错,所以不推荐用ListParts出来的结果生成最后CompleteMultipartUpload的Part列表。

          list_parts方法可供调用的参数还有:

          名称 类型 描述 是否必需
          max_parts Int BOS一次最多返回的part数目,默认1000,最大1000
          part_number_marker Int 按照partNumber排序,本次请求的起始part从此partNumber的下一个开始返回

          list_parts方法返回的解析类中可供调用的参数有:

          参数 说明
          bucket Bucket名称
          key Object名称
          initiated 本次分块上传开始时间
          max_parts 请求返回的最大数目
          is_truncated 指明是否所有查询都返回了;false-本次已经返回所有结果,true-本次还没有返回所有结果
          storage_class Object的存储类型,目前分为标准类型STANDARD, 低频类型STANDARD_IA、冷存储类型COLD 和归档类型ARCHIVE
          part_number_marker 分块开始标记位
          parts 分块列表,list类型
          +part_number 分块编号
          +last_modified 此分块最后一次被修改的时间
          +e_tag 每个上传分块的ETag
          +size 分块内容的大小(字节数)
          upload_id 本次分块上传的id
          owner 对应bucket所属用户信息
          +id Bucket owner的用户id
          +display_name Bucket owner的名称
          next_part_number_marker 本次请求返回的最后一条记录的partNumber,可以作为下一次请求的part_number_marker

          方法二:

          parts = list_all_parts(bucket_name, object_key, upload_id = upload_id)
          for item in parts:
              print item.part_number

          list_all_parts方法返回parts的生成器(Generator),并且不受单次最大返回1000个结果的限制,会返回所有的结果。

          获取分块上传的Object的存储类型

          response = bos_client.list_parts(bucket_name=bucket, 
                            key=object_key, 
                            upload_id=upload_id)
          
          print response.storage_class

          封装分块上传

          在Python SDK中,BOS为用户提供了put_super_obejct_from_file()接口,它对分块上传涉及到的initiate_multipart_upload、upload_part_from_file、complete_multipart_upload三个方法进行封装,用户只需调用该接口即可完成分块上传。

          import multiprocessing
          
          file_name = "/path/to/file.zip"
          result = bos_client.put_super_obejct_from_file(bucket_name, key, file_name,
                      chunk_size=5, thread_num=multiprocessing.cpu_count())
          if result:
              print "Upload success!"

          方法可供调用的参数还有:

          名称 类型 描述 是否必需
          chunk_size int 分块大小,单位MB。默认为5MB
          thread_num int 分块上传中线程池中线程的数量,默认等于CPU的核数

          若一个大文件耗时很长,用户想结束分块上传,可调用UploadTaskHandle中的cancel()方法实现取消分块上传操作。示例如下:

          import threading
          from baidubce.services.bos.bos_client import UploadTaskHandle
          
          file_name = "/path/to/file.zip"
          uploadTaskHandle = UploadTaskHandle()
          t = threading.Thread(target=bos_client.put_super_obejct_from_file, args=(bucket_name, key, file_name),
                  kwargs={
                      "chunk_size": 5,
                      "thread_num": multiprocessing.cpu_count(),
                      "uploadTaskHandle": uploadTaskHandle
                      })
          t.start()
          time.sleep(2)
          uploadTaskHandle.cancel()
          t.join()

          断点续传上传

          当用户向BOS上传大文件时,如果网络不稳定或者遇到程序崩等情况,则整个上传就失败了,失败前已经上传的部分也作废,用户不得不重头再来。这样做不仅浪费资源,在网络不稳定的情况下,往往重试多次还是无法完成上传。 基于上述场景,BOS提供了断点续传上传的能力:

          • 当网络情况一般的情况下,建议使用三步上传方式,将object分为1Mb的块,参考分块上传
          • 当您的网络情况非常差,推荐使用appendObject的方式进行断点续传,每次append 较小数据256kb,参考追加上传

          提示

          • 断点续传是分片上传的封装和加强,是用分片上传实现的;
          • 文件较大或网络环境较差时,推荐使用分片上传;

          下载文件

          BOS Python SDK提供了丰富的文件下载接口,用户可以通过以下方式从BOS中下载文件:

          • 简单流式下载
          • 下载到本地文件
          • 下载为字符串
          • 断点续传下载
          • 范围下载

          简单的读取Object

          用户可以通过如下代码将Object读取到一个流中:

          response = bos_client.get_object(bucket_name, object_key)
          s = response.data
          
          #  处理Object
          ...
          
          # 关闭流
          response.data.close()

          直接下载Object到文件或字符串

          用户可以参考如下代码将Object下载到指定文件:

          bos_client.get_object_to_file(bucket_name, object_key, file_name)

          用户可以参考如下代码将Object下载到字符串:

          result = bos_client.get_object_as_string(bucket_name, object_key)
          print result

          范围下载

          为了实现更多的功能,可以通过使用指定range参数来指定下载范围,实现更精细化地获取Object。如果指定的下载范围是0 - 100,则返回第0到第100个字节的数据,包括第100个,共101字节的数据,即[0, 1000]。

          range = [0,1000]
          #返回指定范围的Object数据
          print bos_client.get_object_as_string(bucket_name, object_key, range = range)
          #返回指定范围的Object数据到文件中
          bos_client.get_object_to_file(bucket_name, object_key, file_name, range = range)

          通过get_object_as_string和get_object_to_file的range参数可以设置返回Object的范围。用户也可以用此功能实现文件的分段下载和断点续传。

          其他使用方法

          获取Object的存储类型

          Object的storage class属性分为STANDARD(标准存储), STANDARD_IA(低频存储),COLD(冷存储)和ARCHIVE(归档存储),通过如下代码可以代码获得Object的storage class属性:

          response = bos_client.get_object_meta_data(bucket_name, object_key)
          print response.metadata.bce_storage_class

          只获取ObjectMetadata

          通过get_object_meta_data方法可以只获取Object的元数据,而非Object实体。如下代码所示:。

          response = bos_client.get_object_meta_data(bucket_name, object_key)

          get_object_meta_data方法返回的解析类中可供调用的参数有:

          参数 说明
          content_length Object的大小
          e_tag Object的HTTP协议实体标签
          bce_meta 如果在PutObject指定了user_metadata自定义meta,则返回此项()
          storageClass Object的存储类型
          bce_restore 归档存储对象处于正在取回或已经取回时返回。对于正在取回的归档对象bce_restore取值为 ongoing-request="true";对于已取回的归档对象bce_restore取值为 ongoing-request="false", expiry-date="Wed, 07 Nov 2019 00:00:00 GMT"。其中expiry-date表示对象取回后的失效时间,此时间为格林尼治时间。

          取回归档存储类型文件

          取回归档类型文件

          用户上传归档文件后,归档文件是处于冰冻状态的,如果要下载归档文件,必须先取回归档存储文件。请求者必须有归档存储文件的读权限,并且归档存储文件处于冰冻状态。

          取回归档文件,示例如下:

          # 取回归档文件并设置解冻后持续时间为2天
          bos_client.restore_object(bucket_name, target_key, days=2)

          判断归档文件是否取回

          对于归档存储对象,如果正在取回或已经取回时返回,获取ObjectMetadata时会返回bce_restore。对于正在取回的归档对象bce_restore取值为 ongoing-request="true";对于已取回的归档对象bce_restore取值为 ongoing-request="false", expiry-date="Wed, 07 Nov 2019 00:00:00 GMT"。其中expiry-date表示对象取回后的失效时间。

          示例如下:

          response = bos_client.get_object_meta_data(bucket_name, object_key)
          if response.metadata.bce_restore is not None:
              if response.metadata.bce_restore.find("expiry-date") >= 0:
                  print("archive object is restored.")
              else:
                  print("archive object is restoring.")
          else:
              print("archvie object is freezed.")

          变更文件存储等级

          上文中已提到,BOS支持为文件赋予STANDARD(标准存储), STANDARD_IA(低频存储)、COLD(冷存储)、ARCHIVE(归档存储)四种存储类型。同时,BOS python SDK也支持用户对特定文件执行存储类型变更的操作。 涉及到的参数如下:

          参数 说明
          x-bce-storage-class 指定Object的存储类型,STANDARD_IA代表低频存储,COLD代表冷存储,ARCHIVE代表冷存储,不指定时默认是标准存储类型。

          注意

          • 调用copy_object()接口时如果源object是归档类型,需要先调用restore_object()取回归档文件。

          示例如下:

          # 标准存储转为低频存储
          bos_client.copy_object(source_bucket_name, source_key,
                                  target_bucket_name, target_key,
                                  storage_class = storage_class.STANDARD_IA)
          # 低频存储转为冷存储
          bos_client.copy_object(source_bucket_name, source_key,
                                  target_bucket_name, target_key,
                                  storage_class = storage_class.COLD)

          获取文件下载URL

          用户可以通过如下示例代码获取指定Object的URL:

          url = bos_client.generate_pre_signed_url(bucket_name, object_key, timestamp, expiration_in_seconds)

          说明:

          • 用户在调用该函数前,需要手动设置endpoint为所属区域域名。百度智能云目前开放了多区域支持,请参考区域选择说明。目前支持“华北-北京”、“华南-广州”和“华东-苏州”三个区域。北京区域:http://bj.bcebos.com,广州区域:http://gz.bcebos.com,苏州区域:http://su.bcebos.com
          • timestamp为可选参数,不配置时,默认值为当前时间。
          • timestamp为时间戳,标识URL有效起始时间,timestamp=int(time.time()),并需要* import time
          • expriation_in_seconds用来设置URL的有效时长,为可选参数,不配置时,默认值为1800秒。如果要设置为永久不失效的时间,可以将expirationInSeconds参数设置为 -1,不可设置为其他负数。
          • 获取文件url接口不支持通过STS方式获取。

          列举存储空间中的文件

          BOS SDK支持用户通过以下两种方式列举出object:

          • 简单列举
          • 通过参数复杂列举

          除此之外,用户还可在列出文件的同时模拟文件夹

          简单列举

          当用户完成一系列上传后,可能会需要查看在指定Bucket中的全部Object,可以通过如下代码实现:

          response = bos_client.list_objects(bucket_name)
          for object in response.contents:
              print object.key

          注意: 1. 默认情况下,如果Bucket中的Object数量大于1000,则只会返回1000个Object,并且返回结果中is_truncated值为True,并返回next_marker做为下次读取的起点。 2. 若想增大返回Object的数目,可以使用Marker参数分次读取。

          也可以一次列举当前Bucket的所有的Object。

          for object in bos_client.list_all_objects(bucket_name):
              print object.key

          通过参数复杂列举

          list_objects方法其他可选的参数有:

          参数 说明
          prefix 限定返回的object key必须以Prefix作为前缀。
          delimiter 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现Delimiter字符之间的object作为一组元素: CommonPrefixes。
          max_keys 限定此次返回object的最大数,此数值不能超过1000,如果不设定,默认为1000。
          marker 设定结果从Marker之后按字母排序的第一个开始返回。

          注意:

          1. 如果有Object以Prefix命名,当仅使用Prefix查询时,返回的所有Key中仍会包含以Prefix命名的Object,详见递归列出目录下所有文件
          2. 如果有Object以Prefix命名,当使用Prefix和Delimiter组合查询时,返回的所有Key中会有Null,Key的名字不包含Prefix前缀,详见查看目录下的文件和子目录

          下面我们分别以几个案例说明通过参数列举的方法:

          指定最大返回条数

              max_keys = 500
              # 指定最大返回条数为500
              response = bos_client.list_objects(bucket_name, max_keys = max_keys)
              for object in response.contents:
                  print object.key

          返回指定前缀的object

              prefix = "test"
              # 指定返回前缀为test的object
              response = bos_client.list_objects(bucket_name, prefix = prefix)
              for object in response.contents:
                  print object.key

          从指定Object后返回

              marker = "object"
              # 用户可以定义不包括某object,从其之后开始返回
              response = bos_client.list_objects(bucket_name, marker = marker)
              for object in response.contents:
                  print object.key

          分页获取所有Object

              isTruncated = True
              # 用户可设置每页最多500条记录
              max_keys = 500
              marker = None
              while isTruncated:
                  response = bos_client.list_objects(bucket_name, max_keys = max_keys, marker=marker)
                  for object in response.contents:
                  	print object.key
                  isTruncated = response.is_truncated
                  marker = getattr(response,'next_marker',None)

          分页获取所有特定Object后的结果

              # 用户可设置每页最多500条记录,并从某特定object之后开始获取
              max_keys = 500
              marker = "object"
              isTruncated = True
              while isTruncated:
              	response = bos_client.list_objects(bucket_name, max_keys = max_keys, marker=marker)
                  for object in response.contents:
                  	print object.key
                  isTruncated = response.is_truncated
                  marker = getattr(response,'next_marker',None)

          分页获取所有指定前缀的Object结果

              # 用户可设置分页获取指定前缀的Object,每页最多500条记录
              max_keys = 500
              prefix = "object"
              isTruncated = True
              while isTruncated:
              	response = bos_client.list_objects(bucket_name, prefix = prefix)
              	for object in response.contents:
              	    print object.key
              	isTruncated = response.is_truncated
                  marker = getattr(response,'next_marker',None)

          list_objects方法返回的解析类中可供调用的参数有:

          参数 说明
          name Bucket名称
          prefix 匹配以prefix开始到第一次出现Delimiter字符之间的object作为一组元素返回
          marker 本次查询的起点
          max_keys 请求返回的最大数目
          is_truncated 指明是否所有查询都返回了;false-本次已经返回所有结果,true-本次还没有返回所有结果
          contents 返回的一个Object的容器
          +key Object名称
          +last_modified 此Object最后一次被修改的时间
          +e_tag Object的HTTP协议实体标签
          +size Object的内容的大小(字节数)
          +owner Object对应Bucket所属用户信息
          ++id Bucket Owner的用户ID
          ++display_name Bucket Owner的名称
          next_marker 只要IsTruncated为true,就会返回next_marker,作为下次查询marker的值
          common_prefixes 仅当指定delimiter,才会返回此项

          list_all_objects方法返回contents的生成器(Generator),并且不受单次最大返回1000个结果的限制,会返回所有的结果。

          模拟文件夹功能

          在BOS的存储结果中是没有文件夹这个概念的,所有元素都是以Object来存储,但BOS的用户在使用数据时往往需要以文件夹来管理文件。 因此,BOS提供了创建模拟文件夹的能力,其本质上来说是创建了一个size为0的Object。对于这个Object可以上传下载,只是控制台会对以”/“结尾的Object以文件夹的方式展示。

          用户可以通过 Delimiter 和 Prefix 参数的配合模拟出文件夹功能。Delimiter 和 Prefix 的组合效果是这样的:

          如果把 Prefix 设为某个文件夹名,就可以罗列以此 Prefix 开头的文件,即该文件夹下递归的所有的文件和子文件夹(目录)。文件名在Contents中显示。 如果再把 Delimiter 设置为 “/” 时,返回值就只罗列该文件夹下的文件和子文件夹(目录),该文件夹下的子文件名(目录)返回在 CommonPrefixes 部分,子文件夹下递归的文件和文件夹不被显示。

          假设Bucket中有5个文件:bos.jpg,fun/,fun/test.jpg,fun/movie/001.avi,fun/movie/007.avi,把 “/” 符号作为文件夹的分隔符。

          如下是几个应用方式:

          列出Bucket内所有文件

          当用户需要获取Bucket下的所有文件时,可以参考分页获取所有Object

          递归列出目录下所有文件

          可以通过设置 Prefix 参数来获取某个目录下所有的文件:

              prefix = "fun/";
              print "Objects:";
              # 递归列出fun目录下的所有文件
              response = bos_client.list_objects(bucket_name, prefix = prefix)
              for object in response.contents:
                  print object.key

          输出:

              Objects:
              fun/
              fun/movie/001.avi
              fun/movie/007.avi
              fun/test.jpg

          查看目录下的文件和子目录

          PrefixDelimiter 结合的情况下,可以列出目录下的文件和子目录:

              # "/" 为文件夹的分隔符
              delimiter = "/"
              prefix = "fun/";
              # 列出fun目录下的所有文件和文件夹
              response = bos_client.list_objects(bucket_name, prefix = prefix, delimiter = delimiter)
              print "Objects:"
              for object in response.contents:
                  print object.key
                  
              # 遍历所有CommonPrefix
              print "CommonPrefixs:"
              for object in response.common_prefixes:
                  print object.prefix

          输出:

              Objects:
              fun/
              fun/test.jpg
          
              CommonPrefixs:
              fun/movie/

          返回的结果中, Objects 的列表中给出的是fun目录下的文件。而 CommonPrefixs 的列表中给出的是fun目录下的所有子文件夹。可以看出 fun/movie/001.avifun/movie/007.avi 两个文件并没有被列出来,因为它们属于 fun 文件夹下的 movie 目录。

          列举Bucket中object的存储属性

          用户除了可以查看指定Bucket中的全部Object,还可以查看Object的存储类型,实现代码如下:

              response = bos_client.list_objects(bucket_name)
              for object in response.contents:
                  print 'object:%s, storage_class:%s' % (object.key, object.storage_class)

          Object权限控制

          设置Object的访问权限

          目前BOS支持两种方式设置ACL。第一种是使用Canned Acl,在PutObjectAcl的时候,通过头域的"x-bce-acl"或者"x-bce-grant-permission'来设置object访问权限,当前可设置的权限包括private和public-read,两种类型的header不可以同时在一个请求中出现。第二种方式是上传一个ACL文件。 详细信息请参考设置Object权限控制

          1. 通过使用头域的"x-bce-acl"来设置object访问权限
              from baidubce.services.bos import canned_acl
              # 设置object为private权限
              bos_client.set_object_canned_acl(bucket_name, object_key, canned_acl=canned_acl.PRIVATE)
              # 设置object为public-read权限
              bos_client.set_object_canned_acl(bucket_name, object_key, canned_acl=canned_acl.PUBLIC_READ)
          1. 通过使用头域的"x-bce-grant-permission'来设置object访问权限
              # 授予指定用户对Object的可读权限。
              bos_client.set_object_canned_acl(bucket_name, object_key, grant_read='id="12345678dfd5487e99f5c85aca5c1234",id="1234567880274ea5a9d50fe94c151234"')
              # 授予指定用户对Object的FULL_CONTROL权限。
              bos_client.set_object_canned_acl(bucket_name, object_key, grant_full_control='id="12345678dfd5487e99f5c85aca5c1234",id="1234567880274ea5a9d50fe94c151234"')
          1. 通过set_object_acl()接口来设置object权限。
              # 授予指定用户对Object的可读权限。
              acl = [{
                         "grantee":[{
                         "id":"12345678dfd5484399f5c85aca5c1234"
                         }],
                         "permission":["READ"]
                     }]
              bos_client.set_object_acl(bucket_name, object_key, acl = acl)

          查看Object的权限

          归档存储类型对象在取回未完成,或者刚上传归档类型文件(时长参考取回时长)时,不能设置Object acl

          查看Object的权限如下代码所示:

              response = bos_client.get_object_acl(bucket_name, object_key)
              print "object acl:", response

          getObjectAcl方法返回的解析类中可供调用的参数有:

          参数 说明
          accessControlList 标识Object的权限列表
          grantee 标识被授权人
          -id 被授权人id
          permission 标识被授权人的权限

          删除Object的权限

          归档存储类型对象在取回未完成,或者刚上传归档类型文件(时长参考取回时长)时,不能删除Object acl

          如下代码可以删除Object的权限:

          bos_client.delete_object_acl(bucket_name,object_key)

          删除文件

          删除一个Object

          如下代码删除了一个Object:

          bos_client.delete_object(bucket_name, object_key)

          批量删除Object

          用户可以通过如下代码批量删除object

              key_list = [object_key1, object_key2, object_key3]
              bos_client.delete_multiple_objects(bucket_name, key_list)

          说明:支持一次请求内最多删除1000个Objcet。

          查看文件是否存在

          用户可通过如下操作查看某文件是否存在:

          from baidubce import exception
          
          try:
          	response = bos_client.get_object_meta_data(bucket_name, object_key)
          	print "Get meta:",response.metadata
          except exception.BceError as e:
          	print e

          获取及更新文件元信息

          文件元信息(Object Metadata),是对用户上传BOS的文件的属性描述,分为两种:HTTP标准属性(HTTP Headers)和User Meta(用户自定义元信息)。

          获取文件元信息

          参考只获取ObjectMetadata

          修改文件元信息

          BOS修改Object的Metadata通过拷贝Object实现。即拷贝Object的时候,把目的Bucket设置为源Bucket,目的Object设置为源Object,并设置新的Metadata,通过拷贝自身实现修改Metadata的目的。如果不设置新的Metadata,则报错。

          归档类型文件不支持修改元信息。

          user_metadata = {'meta_key': 'meta_value'}
          bos_client.copy_object(source_bucket_name = bucket_name, 
                                 source_key = object_name, 
                                 target_bucket_name = bucket_name, 
                                 target_key = object_name, 
                                 user_metadata = user_metadata)
          response = bos_client.get_object_meta_data(bucket_name = bucket_name, 
                                                     key = object_name)
          print response

          拷贝Object

          用户可以通过copyObject方法拷贝一个Object,如下代码所示:

          bos_client.copy_object(source_bucket_name, source_object_key, target_bucket_name, target_object_key)

          同步Copy功能

          当前BOS的CopyObject接口是通过同步方式实现的。同步方式下,BOS端会等待Copy实际完成才返回成功。同步Copy能帮助用户更准确的判断Copy状态,但用户感知的复制时间会变长,且复制时间和文件大小成正比。

          同步Copy方式更符合业界常规,提升了与其它平台的兼容性。同步Copy方式还简化了BOS服务端的业务逻辑,提高了服务效率。

          归档类型文件如果是源Object,需要先取回归档类型文件。

          如果您使用bce-python-sdk-0.8.12版本之前的SDK,有可能会出现复制请求成功,但文件实际复制失败的情况,所以建议您使用最新版本SDK。

          分块拷贝

          除了通过CopyObject接⼝拷贝文件以外,BOS还提供了另外一种拷贝模式——Multipart Upload Copy。归档类型文件如果是源Object,需要先取回归档类型文件。

          用户可以在如下的应用场景内(但不仅限于此),使用Multipart Upload Copy,如:

          • 需要支持断点拷贝。
          • 拷贝超过5GB大小的文件。
          • 网络条件较差,和BOS的服务器之间的连接经常断开。

          下面将介绍分步实现三步拷贝。

          三步拷贝包含init、“拷贝分块”和complete三步,其中init和complete的操作同分块上传一致,可直接参考初始化Multipart Upload完成分块上传

          拷贝分块代码参考:

          left_size = int(bos_client.get_object_meta_data(source_bucket,source_key).metadata.content_length)
          #设置分块开始位置为left_size
          
          #设置分块的开始偏移位置
          offset = 0
          part_number = 1
          part_list = []
          while left_size > 0:
          
              #设置每块为5MB
              part_size = 5 * 1024 * 1024
              if left_size < part_size:
                  part_size = left_size
          
             	response = bos_client.upload_part_copy(source_bucket, source_key, target_bucket, target_key, upload_id,part_number, part_size, offset)
          
             	left_size -= part_size
             	offset += part_size
             	part_list.append({
             		"partNumber": part_number,
             		"eTag": response.etag
             	})
          
             	part_number += 1

          注意:

          1. offset参数以字节为单位,为分块的开始偏移位置。
          2. size参数以字节为单位,定义每个分块的大小,除最后一个Part以外,其他的Part大小都要大于 5MB。

          选取文件

          SelectObject接口支持用户对BOS中指定格式(CSV/JSON)的object内容执行SQL语句,通过SQL这种结构化查询语言对object内容进行筛选、分析、过滤之后再返回用户需要的文件内容。

          使用限制见“开发者指南“-”使用及管理数据”-“选取object”部分。

          查询csv文件示例:

              from baidubce import compat
              import base64
              
              # 方便理解,我们先上传一个简单的csv文件
              csv_content = """
                  1,Maurits,2017-09-1216:32:57,685856330,-540265154.48,true
                  2,Iago,2018-02-01 12:25:01,-642946677,3781354659.89,false
                  3,Dionisio,2018-02-16 09:52:24,-3823711977,79336720.77,false
                  4,Aleen,2018-05-17 11:48:45,-3289131518,1499686289.41,false
                  5,Herschel,2019-06-04 02:28:37,3456163349,-3810272511.88,true
                  """
              bos_client.put_object_from_string(bucket_name, key, csv_content)
              # 设置select_object()接口的参数
              select_object_args = {
                  "expressionType": "SQL",
                  "inputSerialization": {
                      "compressionType": "NONE",
                      "csv": {
                          "fileHeaderInfo": "NONE",
                          "recordDelimiter": "Cg==",
                          "fieldDelimiter": "LA==",
                          "quoteCharacter": "Ig==",
                          "commentCharacter": "Iw=="
                      }
                  },
                  "outputSerialization": {
                      "outputHeader": False,
                      "csv": {
                          "quoteFields": "ALWAYS",
                          "recordDelimiter": "Cg==",
                          "fieldDelimiter": "LA==",
                          "quoteCharacter": "Ig=="
                      }
                  },
                  "requestProgress": {
                      "enabled": True
                  }
              }
              # 设置查询的sql语句,需要经过base64编码的sql语句
              sql_exp = "SELECT _1, _2, _6 FROM BosObject"
              select_object_args["expression"] = compat.convert_to_string(base64.standard_b64encode(compat.convert_to_bytes(sql_exp)))
              # 调用select object接口
              select_response = bos_client.select_object(bucket_name, key, select_object_args)
              # 获取返回结果的生成器
              result = select_response.result()
              for msg in result:
                  print(msg)
                  if msg.headers["message-type"] == "Records":
                      print("type: {}, heades: {}, payload: {}, crc: {}".format(msg.type, msg.headers, msg.payload, msg.crc))
                  elif msg.headers["message-type"] == "Cont":
                      print("type: {}, heades: {}, bytes_scanned: {}, bytes_returned: {},  crc: {}".format(msg.type, msg.headers,
                          msg.bytes_scanned, msg.bytes_returned, msg.crc))
                  else:
                      print("type: {}, heades: {}, crc: {}".format(msg.type, msg.headers, msg.crc))

          查询json文件示例:

              from baidubce import compat
              import base64
              
              # 方便理解,我们先上传一个简单的json文件
              json_content = """
              {
              "name": "Smith",
              "age": 16,
              "weight": 65.5,
              "org": null,
              "projects":
                  [
                   {"project_name":"project1", "completed":false},
                   {"project_name":"project2", "completed":true}
                  ]
              }
              """
              bos_client.put_object_from_string(bucket_name, key, json_content)
              # 设置select_object()接口的参数
              select_object_args = {
                  "expressionType": "SQL",
                  "inputSerialization": {
                      "compressionType": "NONE",
                      "json": {
                          "type": "DOCUMENT"
                      }
                  },
                  "outputSerialization": {
                      "json": {
                          "recordDelimiter": "Cg=="
                      }
                  },
                  "requestProgress": {
                      "enabled": True
                  }
              }
              # 设置查询的sql语句,需要经过base64编码的sql语句
              sql_exp = "select projects from BosObject where name='Smith'"
              select_object_args["expression"] = compat.convert_to_string(base64.standard_b64encode(compat.convert_to_bytes(sql_exp)))
              # 调用select object接口
              select_response = bos_client.select_object(bucket_name, key, select_object_args)
              # 获取返回结果的生成器
              result = select_response.result()
              for msg in result:
                  print(msg)
                  if msg.headers["message-type"] == "Records":
                      print("type: {}, heades: {}, payload: {}, crc: {}".format(msg.type, msg.headers, msg.payload, msg.crc))
                  elif msg.headers["message-type"] == "Cont":
                      print("type: {}, heades: {}, bytes_scanned: {}, bytes_returned: {},  crc: {}".format(msg.type, msg.headers,
                          msg.bytes_scanned, msg.bytes_returned, msg.crc))
                  else:
                      print("type: {}, heades: {}, crc: {}".format(msg.type, msg.headers, msg.crc))

          软链接

          创建软链接

          本接口用于为BOS中相同bucket下已有的目的object(本文档称作"target object")创建软链接(Symlink),您可以通过该软链接访问目的object。相关API介绍见PutSymlink

          注意:

          • 软链接文件和target object文件需要位于同一个bucket下面。
          • 目前支持对标准存储、低频存储、冷存储、归档存储类型的object文件设置软链接。软链接文件本身不支持ARCHIVE类型。如果用户指定ARCHIVE类型,或者不指定类型且Bucket默认存储类型是ARCHIVE时,返回报错InvalidArgument。
          • 调用该接口创建软链接时,不会检查目标文件是否存在、以及是否有权限访问目标文件。使用软链接调用GetObject接口时候,会检查用户是否有软链接和目标文件的读取权限、目标文件是否存在。
          • 创建软链接需要有相应写权限。
          • 如果不指定"forbid_overwrite",且如果存在与软链接文件同名的object文件时,创建软链接操作时会默认覆盖同名Object。
          • 不支持二级软链接。用户创建二级软链时不会进行检查,但是用户无法通过二级软链访问指向的object数据。

          创建软链接可选参数:

          名称 类型 描述 是否必选
          forbid_overwrite bool 指定创建软链接操作时是否覆盖同名Object。如果不指定x-bce-forbid-overwrite时,默认允许覆盖同名Object。指定x-bce-forbid-overwrite为true时,表示禁止覆盖同名Object;指定x-bce-forbid-overwrite为false时,表示允许覆盖同名Object。
          storage_class string 设置存储类型,软链接不支持归档类型。不设置时使用当前bucket的存储类型

          示例如下:

          symlink_key = "mySymlink"
          bos_client.put_object_from_string(bucket_name, key, "This is string content.")
          
          # 创建软链接示例1
          bos_client.put_object_symlink(bucket_name, key, symlink_key)
          # 创建软链接示例2
          bos_client.put_object_symlink(bucket_name, key, symlink_key,
              forbid_overwrite=Fasle, storage_class=storage_class.STANDARD)

          获取软链接

          接口用于获取软链接。此操作需要您对该软链接有读权限。

          示例如下:

          symlink_key = "mySymlink"
          
          # 获取软链接,并打印目标文件
          respones = bos_client.get_object_symlink(bucket_name, symlink_key)
          print response.metadata.bce_symlink_target
          
          # 使用软链接获取元信息
          respones = bos_client.get_object_meta_data(bucket_name, symlink_key)
          # 如果是软链接类型,返回bce_object_type = “Symlink”
          print response.metadata.bce_object_type
          
          # 使用软链接下载目的文件
          content = bos_client.get_object_as_string(bucket_name, symlink_key)
          print content
          上一篇
          Bucket管理
          下一篇
          日志控制