11#!/usr/bin/env python
2+ import os
23import boto3
4+ from boto3 .s3 .transfer import TransferConfig , S3Transfer
5+ from tqdm import tqdm # For progress bar
36from botocore .exceptions import ClientError
47
58from bento .common .utils import get_logger
@@ -55,14 +58,29 @@ def file_exists_on_s3(self, key):
5558 self .log .exception (e )
5659 return False , msg
5760
58- def put_file_obj (self , key , data , md5_base64 ):
59- return self .bucket .put_object (Key = key ,
60- Body = data ,
61- ContentMD5 = md5_base64 ,
62- ACL = BUCKET_OWNER_ACL )
61+ def put_file_obj (self , file_size , key , data , md5_base64 ):
62+ # Initialize the progress bar
63+ progress = create_progress_bar (file_size )
64+ chunk_size = 1024 * 1024 if file_size >= 1024 * 1024 else file_size #chunk data for display progress for small metadata file < 4,500,000,000 bytes
65+ try :
66+ # Upload the file in chunks
67+ for chunk in iter (lambda : data .read (chunk_size ), b'' ):
68+ self .bucket .put_object (Key = key ,
69+ Body = chunk ,
70+ ContentMD5 = md5_base64 ,
71+ ACL = BUCKET_OWNER_ACL ,
72+ )
73+ # Update the progress bar
74+ progress .update (len (chunk ))
75+ finally :
76+ # Close the progress bar
77+ progress .close ()
6378
64- def upload_file_obj (self , key , data , config = None , extra_args = {'ACL' : BUCKET_OWNER_ACL }):
65- return self .bucket .upload_fileobj (data , key , ExtraArgs = extra_args , Config = config )
79+ def upload_file_obj (self , file_size , key , data , config = None , extra_args = {'ACL' : BUCKET_OWNER_ACL }):
80+ self .bucket .upload_fileobj (
81+ data , key , ExtraArgs = extra_args , Config = config ,
82+ Callback = ProgressPercentage (file_size )
83+ )
6684
6785 def get_object_size (self , key ):
6886 try :
@@ -90,7 +108,9 @@ def same_size_file_exists(self, key, file_size):
90108
91109 def download_object (self , key , local_file_path ):
92110 try :
93- self .bucket .download_file ( key , local_file_path )
111+ file_size , msg = self .get_object_size (key )
112+ self .bucket .download_file (key , local_file_path ,
113+ Callback = ProgressPercentage (file_size ))
94114 return True , None
95115 except ClientError as ce :
96116 msg = None
@@ -115,5 +135,26 @@ def close(self):
115135 self .client = None
116136 self .bucket = None
117137 self .s3 = None
138+
139+ """
140+ S3 util class to display upload progress
141+ """
142+ class ProgressPercentage (object ):
143+ def __init__ (self , file_size ):
144+ self ._size = file_size
145+ self ._seen_so_far = 0
146+ self ._progress = create_progress_bar (file_size )
147+
148+ def __call__ (self , bytes_amount ):
149+ self ._seen_so_far += bytes_amount
150+ self ._progress .update (bytes_amount )
151+
152+ def __del__ (self ):
153+ self ._progress .close ()
154+
155+ def create_progress_bar (file_size ):
156+ progress_bar = tqdm (total = file_size , unit = 'B' , unit_scale = True , desc = "Progress" , smoothing = 0.0 ,
157+ bar_format = "{l_bar}\033 [1;32m{bar}\033 [0m| {n_fmt}/{total_fmt} [elapsed: {elapsed} | remaining: {remaining}, {rate_fmt}]" )
158+ return progress_bar
118159
119160
0 commit comments