python多线程实现S3文件分段上传下载

对于大对象的存取,s3提供了分段上传/下载的接口,基于此,可以进一步实现多线程并行传输或者断点续传等功能。

本实现使用了亚马逊的boto库

https://pypi.python.org/pypi/boto

以及filechunkio库

https://pypi.python.org/pypi/filechunkio/

from boto.s3.connection import S3Connection,OrdinaryCallingFormat,SubdomainCallingFormat

import ssl

import boto.s3.key

import os

import json

import random

import fire

import math

from filechunkio import FileChunkIO

class S3(object):

    def __init__(self,host,access_key_id,secret_access_key,port=443,is_secure=True):

        if is_secure:

            ssl._create_default_https_context =ssl._create_unverified_context

        self._secure=is_secure

        self.host=host

        self.access_key_id=access_key_id

        self.secret_access_key=secret_access_key

        self.port=port

        self._connection=False

        self._client=None

    # def __del__(self):

    #    self._client.closed()

    def connect(self,aws=False):

        try:

            if aws:

                calling_format=SubdomainCallingFormat()

            else:

                calling_format=OrdinaryCallingFormat()

            conn = S3Connection(

                host=self.host,

                aws_access_key_id=self.access_key_id,

                aws_secret_access_key=self.secret_access_key,

                port=self.port,

                debug=1,

                is_secure=self._secure,

                calling_format=calling_format

            )

            self._connection=True

            self._client=conn

        except Exception as e:

            self._connection=False

            print(e)

    def create_bucket(self,bucket):

        try:

            bucket=self._client.create_bucket(bucket)

        except Exception as e:

            print(e)

            print(bucket)

    def delete_bucket(self,bucket):

        try:

            bucket=self._client.get_bucket(bucket)

            bucket.delete()

        except Exception as e:

            print(e)

            print(bucket)

    def set_acl(self):

        pass

    def delete_bucket_force(self,bucket):

        try:

            bucket=self._client.get_bucket(bucket)

            for obj in bucket.list():

                obj.delete()

            bucket.delete()

        except Exception as e:

            print(e)

            print(bucket)


    def upload_file(self,bucket,file_path,path=''):

        try:

            bucket=self._client.get_bucket(bucket)

            key=bucket.new_key(path+os.path.basename(file_path))

            key.set_contents_from_filename(file_path)

            return True

        except Exception as e:

            print(e)

            return False

    def chunk_upload_file(self,bucket,file_path):

        try:

            source_path = file_path

            source_size = os.stat(file_path).st_size

            chunk_size = 52428800

            chunk_count = int(math.ceil(source_size / float(chunk_size)))

            bucket=self._client.get_bucket(bucket)

            mp=bucket.initiate_multipart_upload(os.path.basename(file_path))

            for i in range(chunk_count):

                offset = chunk_size * i

                bytes_ = min(chunk_size, source_size - offset)

                with FileChunkIO(source_path, 'r', offset=offset,bytes=bytes_) as fp:

                    mp.upload_part_from_file(fp, part_num=i + 1)


            mp.complete_upload()

            return True

        except Exception as e:

            print(e)

            return False


if __name__ == "__main__":

    s3_obj=S3("host","id","key",443,True)

    s3_obj.connect()

    fire.Fire({

        "upload":s3_obj.upload_file,

        "mp_upload":s3_obj.chunk_upload_file,

        "create_bucket":s3_obj.create_bucket

    })

你可能感兴趣的:(python多线程实现S3文件分段上传下载)