@@ -249,7 +249,7 @@ def make_blob_public(bucket_name, blob_name):
249249
250250
251251def generate_signed_url (bucket_name , blob_name ):
252- """Generates a signed URL for a blob.
252+ """Generates a v2 signed URL for downloading a blob.
253253
254254 Note that this method requires a service account key file. You can not use
255255 this if you are using Application Default Credentials from Google Compute
@@ -269,6 +269,62 @@ def generate_signed_url(bucket_name, blob_name):
269269 return url
270270
271271
272+ # [START storage_generate_signed_url_v4]
273+ def generate_download_signed_url_v4 (bucket_name , blob_name ):
274+ """Generates a v4 signed URL for downloading a blob.
275+
276+ Note that this method requires a service account key file. You can not use
277+ this if you are using Application Default Credentials from Google Compute
278+ Engine or from the Google Cloud SDK.
279+ """
280+ storage_client = storage .Client ()
281+ bucket = storage_client .get_bucket (bucket_name )
282+ blob = bucket .blob (blob_name )
283+
284+ url = blob .generate_signed_url (
285+ version = 'v4' ,
286+ # This URL is valid for 15 minutes
287+ expiration = datetime .timedelta (minutes = 15 ),
288+ # Allow GET requests using this URL.
289+ method = 'GET' )
290+
291+ print ('Generated GET signed URL:' )
292+ print (url )
293+ print ('You can use this URL with any user agent, for example:' )
294+ print ('curl \' {}\' ' .format (url ))
295+ return url
296+ # [END storage_generate_signed_url_v4]
297+
298+
299+ # [START storage_generate_upload_signed_url_v4]
300+ def generate_upload_signed_url_v4 (bucket_name , blob_name ):
301+ """Generates a v4 signed URL for uploading a blob using HTTP PUT.
302+
303+ Note that this method requires a service account key file. You can not use
304+ this if you are using Application Default Credentials from Google Compute
305+ Engine or from the Google Cloud SDK.
306+ """
307+ storage_client = storage .Client ()
308+ bucket = storage_client .get_bucket (bucket_name )
309+ blob = bucket .blob (blob_name )
310+
311+ url = blob .generate_signed_url (
312+ version = 'v4' ,
313+ # This URL is valid for 15 minutes
314+ expiration = datetime .timedelta (minutes = 15 ),
315+ # Allow GET requests using this URL.
316+ method = 'PUT' ,
317+ content_type = 'application/octet-stream' )
318+
319+ print ('Generated PUT signed URL:' )
320+ print (url )
321+ print ('You can use this URL with any user agent, for example:' )
322+ print ("curl -X PUT -H 'Content-Type: application/octet-stream' "
323+ "--upload-file my-file '{}'" .format (url ))
324+ return url
325+ # [END storage_generate_upload_signed_url_v4]
326+
327+
272328def rename_blob (bucket_name , blob_name , new_name ):
273329 """Renames a blob."""
274330 storage_client = storage .Client ()
@@ -296,7 +352,7 @@ def copy_blob(bucket_name, blob_name, new_bucket_name, new_blob_name):
296352 destination_bucket .name ))
297353
298354
299- if __name__ == '__main__' :
355+ def main () :
300356 parser = argparse .ArgumentParser (
301357 description = __doc__ ,
302358 formatter_class = argparse .RawDescriptionHelpFormatter )
@@ -350,6 +406,14 @@ def copy_blob(bucket_name, blob_name, new_bucket_name, new_blob_name):
350406 'signed-url' , help = generate_signed_url .__doc__ )
351407 signed_url_parser .add_argument ('blob_name' )
352408
409+ signed_url_download_v4_parser = subparsers .add_parser (
410+ 'signed-url-download-v4' , help = generate_download_signed_url_v4 .__doc__ )
411+ signed_url_download_v4_parser .add_argument ('blob_name' )
412+
413+ signed_url_upload_v4_parser = subparsers .add_parser (
414+ 'signed-url-upload-v4' , help = generate_upload_signed_url_v4 .__doc__ )
415+ signed_url_upload_v4_parser .add_argument ('blob_name' )
416+
353417 rename_parser = subparsers .add_parser ('rename' , help = rename_blob .__doc__ )
354418 rename_parser .add_argument ('blob_name' )
355419 rename_parser .add_argument ('new_name' )
@@ -363,15 +427,15 @@ def copy_blob(bucket_name, blob_name, new_bucket_name, new_blob_name):
363427
364428 if args .command == 'create-bucket' :
365429 create_bucket (args .bucket_name )
366- if args .command == 'enable-default-kms-key' :
430+ elif args .command == 'enable-default-kms-key' :
367431 enable_default_kms_key (args .bucket_name , args .kms_key_name )
368432 elif args .command == 'delete-bucket' :
369433 delete_bucket (args .bucket_name )
370- if args .command == 'get-bucket-labels' :
434+ elif args .command == 'get-bucket-labels' :
371435 get_bucket_labels (args .bucket_name )
372- if args .command == 'add-bucket-label' :
436+ elif args .command == 'add-bucket-label' :
373437 add_bucket_label (args .bucket_name )
374- if args .command == 'remove-bucket-label' :
438+ elif args .command == 'remove-bucket-label' :
375439 remove_bucket_label (args .bucket_name )
376440 elif args .command == 'list' :
377441 list_blobs (args .bucket_name )
@@ -401,6 +465,10 @@ def copy_blob(bucket_name, blob_name, new_bucket_name, new_blob_name):
401465 make_blob_public (args .bucket_name , args .blob_name )
402466 elif args .command == 'signed-url' :
403467 generate_signed_url (args .bucket_name , args .blob_name )
468+ elif args .command == 'signed-url-download-v4' :
469+ generate_download_signed_url_v4 (args .bucket_name , args .blob_name )
470+ elif args .command == 'signed-url-upload-v4' :
471+ generate_upload_signed_url_v4 (args .bucket_name , args .blob_name )
404472 elif args .command == 'rename' :
405473 rename_blob (args .bucket_name , args .blob_name , args .new_name )
406474 elif args .command == 'copy' :
@@ -409,3 +477,7 @@ def copy_blob(bucket_name, blob_name, new_bucket_name, new_blob_name):
409477 args .blob_name ,
410478 args .new_bucket_name ,
411479 args .new_blob_name )
480+
481+
482+ if __name__ == '__main__' :
483+ main ()
0 commit comments