'Loads a local file to S3
:param filename: name of the file to load.
:type filename: str
:param key: S3 key that will point to the file
:type key: str
:param bucket_name: Name of the bucket in which to store the file
:type bucket_name: str
:param replace: A flag to decide whether or not to overwrite the key
if it already exists. If replace is False and the key exists, an
error will be raised.
:type replace: bool
:param multipart_bytes: If provided, the file is uploaded in parts of
this size (minimum 5242880). The default value is 5GB, since S3
cannot accept non-multipart uploads for files larger than 5GB. If
the file is smaller than the specified limit, the option will be
ignored.
:type multipart_bytes: int
:param encrypt: If True, the file will be encrypted on the server-side
by S3 and will be stored in an encrypted form while at rest in S3.
:type encrypt: bool'

def load_file(self, filename, key, bucket_name=None, replace=False, multipart_bytes=(5 * (1024 ** 3)), encrypt=False):

    if (not bucket_name):
        (bucket_name, key) = self.parse_s3_url(key)
    bucket = self.get_bucket(bucket_name)
    key_obj = bucket.get_key(key)
    if ((not replace) and key_obj):
        raise ValueError('The    key    {key}    already    exists.'.format(**locals()))
    key_size = os.path.getsize(filename)
    if (multipart_bytes and (key_size >= multipart_bytes)):
        from filechunkio import FileChunkIO
        mp = bucket.initiate_multipart_upload(key_name=key, encrypt_key=encrypt)
        total_chunks = int(math.ceil((key_size / multipart_bytes)))
        sent_bytes = 0
        try:
            for chunk in range(total_chunks):
                offset = (chunk * multipart_bytes)
                bytes = min(multipart_bytes, (key_size - offset))
                with FileChunkIO(filename, 'r', offset=offset, bytes=bytes) as fp:
                    logging.info('Sending    chunk    {c}    of    {tc}...'.format(c=(chunk + 1), tc=total_chunks))
                    mp.upload_part_from_file(fp, part_num=(chunk + 1))
        except:
            mp.cancel_upload()
            raise
        mp.complete_upload()
    else:
        if (not key_obj):
            key_obj = bucket.new_key(key_name=key)
        key_size = key_obj.set_contents_from_filename(filename, replace=replace, encrypt_key=encrypt)
    logging.info('The    key    {key}    now    contains    {key_size}    bytes'.format(**locals()))
