|
6 | 6 | .. _here: |
7 | 7 | http://docs.keboola.apiary.io/#reference/files/ |
8 | 8 | """ |
| 9 | +import json |
9 | 10 | import os |
10 | 11 | import boto3 |
11 | 12 | import requests |
12 | 13 |
|
| 14 | +from azure.storage.blob import BlobServiceClient, ContentSettings |
13 | 15 | from kbcstorage.base import Endpoint |
14 | 16 |
|
15 | 17 |
|
@@ -71,36 +73,20 @@ def upload_file(self, file_path, tags=None, is_public=False, |
71 | 73 | if compress: |
72 | 74 | import gzip |
73 | 75 | import shutil |
74 | | - with open(file_path, 'rb') as f_in, gzip.open(file_path + '.gz', |
75 | | - 'wb') as f_out: |
| 76 | + with open(file_path, 'rb') as f_in, \ |
| 77 | + gzip.open(file_path + '.gz', 'wb') as f_out: |
76 | 78 | shutil.copyfileobj(f_in, f_out) |
77 | 79 | file_path = file_path + '.gz' |
78 | 80 | file_name = os.path.basename(file_path) |
79 | 81 | size = os.path.getsize(file_path) |
80 | 82 | file_resource = self.prepare_upload(file_name, size, tags, is_public, |
81 | 83 | is_permanent, is_encrypted, |
82 | 84 | is_sliced, do_notify, True) |
83 | | - upload_params = file_resource['uploadParams'] |
84 | | - key_id = upload_params['credentials']['AccessKeyId'] |
85 | | - key = upload_params['credentials']['SecretAccessKey'] |
86 | | - token = upload_params['credentials']['SessionToken'] |
87 | | - s3 = boto3.resource('s3', aws_access_key_id=key_id, |
88 | | - aws_secret_access_key=key, |
89 | | - aws_session_token=token, |
90 | | - region_name=file_resource['region']) |
| 85 | + if file_resource['provider'] == 'azure': |
| 86 | + self.__upload_to_azure(file_resource, file_path) |
| 87 | + elif file_resource['provider'] == 'aws': |
| 88 | + self.__upload_to_aws(file_resource, file_path, is_encrypted) |
91 | 89 |
|
92 | | - s3_object = s3.Object(bucket_name=upload_params['bucket'], |
93 | | - key=upload_params['key']) |
94 | | - disposition = 'attachment; filename={};'.format(file_resource['name']) |
95 | | - with open(file_path, mode='rb') as file: |
96 | | - if is_encrypted: |
97 | | - encryption = upload_params['x-amz-server-side-encryption'] |
98 | | - s3_object.put(ACL=upload_params['acl'], Body=file, |
99 | | - ContentDisposition=disposition, |
100 | | - ServerSideEncryption=encryption) |
101 | | - else: |
102 | | - s3_object.put(ACL=upload_params['acl'], Body=file, |
103 | | - ContentDisposition=disposition) |
104 | 90 | return file_resource['id'] |
105 | 91 |
|
106 | 92 | def prepare_upload(self, name, size_bytes=None, tags=None, is_public=False, |
@@ -193,32 +179,116 @@ def download(self, file_id, local_path): |
193 | 179 | os.mkdir(local_path) |
194 | 180 | file_info = self.detail(file_id=file_id, federation_token=True) |
195 | 181 | local_file = os.path.join(local_path, file_info['name']) |
196 | | - s3 = boto3.resource( |
197 | | - 's3', |
198 | | - aws_access_key_id=file_info['credentials']['AccessKeyId'], |
199 | | - aws_secret_access_key=file_info['credentials']['SecretAccessKey'], |
200 | | - aws_session_token=file_info['credentials']['SessionToken'], |
201 | | - region_name=file_info['region'] |
202 | | - ) |
203 | | - if file_info['isSliced']: |
204 | | - manifest = requests.get(url=file_info['url']).json() |
205 | | - file_names = [] |
206 | | - for entry in manifest["entries"]: |
207 | | - full_path = entry["url"] |
208 | | - file_name = full_path.rsplit("/", 1)[1] |
209 | | - file_names.append(file_name) |
210 | | - splitted_path = full_path.split("/") |
211 | | - file_key = "/".join(splitted_path[3:]) |
212 | | - bucket = s3.Bucket(file_info['s3Path']['bucket']) |
213 | | - bucket.download_file(file_key, file_name) |
214 | | - # merge the downloaded files |
215 | | - with open(local_file, mode='wb') as out_file: |
216 | | - for file_name in file_names: |
217 | | - with open(file_name, mode='rb') as in_file: |
218 | | - for line in in_file: |
219 | | - out_file.write(line) |
220 | | - os.remove(file_name) |
221 | | - else: |
222 | | - bucket = s3.Bucket(file_info["s3Path"]["bucket"]) |
223 | | - bucket.download_file(file_info["s3Path"]["key"], local_file) |
| 182 | + if file_info['provider'] == 'azure': |
| 183 | + if file_info['isSliced']: |
| 184 | + self.__download_sliced_file_from_azure(file_info, local_file) |
| 185 | + else: |
| 186 | + self.__download_file_from_azure(file_info, local_file) |
| 187 | + elif file_info['provider'] == 'aws': |
| 188 | + s3 = boto3.resource( |
| 189 | + 's3', |
| 190 | + aws_access_key_id=file_info['credentials']['AccessKeyId'], |
| 191 | + aws_secret_access_key=file_info['credentials']['SecretAccessKey'], |
| 192 | + aws_session_token=file_info['credentials']['SessionToken'], |
| 193 | + region_name=file_info['region'] |
| 194 | + ) |
| 195 | + if file_info['isSliced']: |
| 196 | + self.__download_sliced_file_from_aws(file_info, local_file, s3) |
| 197 | + else: |
| 198 | + self.__download_file_from_aws(file_info, local_file, s3) |
224 | 199 | return local_file |
| 200 | + |
| 201 | + def __upload_to_azure(self, preparation_result, file_path): |
| 202 | + blob_client = self.__get_blob_client( |
| 203 | + preparation_result['absUploadParams']['absCredentials']['SASConnectionString'], |
| 204 | + preparation_result['absUploadParams']['container'], |
| 205 | + preparation_result['absUploadParams']['blobName'] |
| 206 | + ) |
| 207 | + with open(file_path, "rb") as blob_data: |
| 208 | + blob_client.upload_blob( |
| 209 | + blob_data, |
| 210 | + blob_type='BlockBlob', |
| 211 | + content_settings=ContentSettings( |
| 212 | + content_disposition='attachment;filename="%s"' % (preparation_result['name']) |
| 213 | + ) |
| 214 | + ) |
| 215 | + |
| 216 | + def __upload_to_aws(self, prepare_result, file_path, is_encrypted): |
| 217 | + upload_params = prepare_result['uploadParams'] |
| 218 | + key_id = upload_params['credentials']['AccessKeyId'] |
| 219 | + key = upload_params['credentials']['SecretAccessKey'] |
| 220 | + token = upload_params['credentials']['SessionToken'] |
| 221 | + s3 = boto3.resource('s3', aws_access_key_id=key_id, |
| 222 | + aws_secret_access_key=key, |
| 223 | + aws_session_token=token, |
| 224 | + region_name=prepare_result['region']) |
| 225 | + s3_object = s3.Object(bucket_name=upload_params['bucket'], key=upload_params['key']) |
| 226 | + disposition = 'attachment; filename={};'.format(prepare_result['name']) |
| 227 | + with open(file_path, mode='rb') as file: |
| 228 | + if is_encrypted: |
| 229 | + encryption = upload_params['x-amz-server-side-encryption'] |
| 230 | + s3_object.put(ACL=upload_params['acl'], Body=file, |
| 231 | + ContentDisposition=disposition, ServerSideEncryption=encryption) |
| 232 | + else: |
| 233 | + s3_object.put(ACL=upload_params['acl'], Body=file, |
| 234 | + ContentDisposition=disposition) |
| 235 | + |
| 236 | + def __download_file_from_aws(self, file_info, destination, s3): |
| 237 | + bucket = s3.Bucket(file_info["s3Path"]["bucket"]) |
| 238 | + bucket.download_file(file_info["s3Path"]["key"], destination) |
| 239 | + |
| 240 | + def __download_sliced_file_from_aws(self, file_info, destination, s3): |
| 241 | + manifest = requests.get(url=file_info['url']).json() |
| 242 | + file_names = [] |
| 243 | + for entry in manifest["entries"]: |
| 244 | + full_path = entry["url"] |
| 245 | + file_name = full_path.rsplit("/", 1)[1] |
| 246 | + file_names.append(file_name) |
| 247 | + splitted_path = full_path.split("/") |
| 248 | + file_key = "/".join(splitted_path[3:]) |
| 249 | + bucket = s3.Bucket(file_info['s3Path']['bucket']) |
| 250 | + bucket.download_file(file_key, file_name) |
| 251 | + self.__merge_split_files(file_names, destination) |
| 252 | + |
| 253 | + def __download_file_from_azure(self, file_info, destination): |
| 254 | + blob_client = self.__get_blob_client( |
| 255 | + file_info['absCredentials']['SASConnectionString'], |
| 256 | + file_info['absPath']['container'], |
| 257 | + file_info['absPath']['name'] |
| 258 | + ) |
| 259 | + with open(destination, "wb") as downloaded_blob: |
| 260 | + download_stream = blob_client.download_blob() |
| 261 | + downloaded_blob.write(download_stream.readall()) |
| 262 | + |
| 263 | + def __download_sliced_file_from_azure(self, file_info, destination): |
| 264 | + blob_service_client = BlobServiceClient.from_connection_string( |
| 265 | + file_info['absCredentials']['SASConnectionString'] |
| 266 | + ) |
| 267 | + container_client = blob_service_client.get_container_client( |
| 268 | + container=file_info['absPath']['container'] |
| 269 | + ) |
| 270 | + manifest_stream = container_client.download_blob( |
| 271 | + file_info['absPath']['name'] + 'manifest' |
| 272 | + ) |
| 273 | + manifest = json.loads(manifest_stream.readall()) |
| 274 | + file_names = [] |
| 275 | + for entry in manifest['entries']: |
| 276 | + blob_path = entry['url'].split('blob.core.windows.net/%s/' % (file_info['absPath']['container']))[1] |
| 277 | + full_path = entry["url"] |
| 278 | + file_name = full_path.rsplit("/", 1)[1] |
| 279 | + file_names.append(file_name) |
| 280 | + with open(file_name, "wb") as file_slice: |
| 281 | + file_slice.write(container_client.download_blob(blob_path).readall()) |
| 282 | + self.__merge_split_files(file_names, destination) |
| 283 | + |
| 284 | + def __merge_split_files(self, file_names, destination): |
| 285 | + with open(destination, mode='wb') as out_file: |
| 286 | + for file_name in file_names: |
| 287 | + with open(file_name, mode='rb') as in_file: |
| 288 | + for line in in_file: |
| 289 | + out_file.write(line) |
| 290 | + os.remove(file_name) |
| 291 | + |
| 292 | + def __get_blob_client(self, connection_string, container, blob_name): |
| 293 | + blob_service_client = BlobServiceClient.from_connection_string(connection_string) |
| 294 | + return blob_service_client.get_blob_client(container=container, blob=blob_name) |
0 commit comments