diff --git a/.doc_gen/metadata/s3_metadata.yaml b/.doc_gen/metadata/s3_metadata.yaml
index b3e0532a61e..690b616c405 100644
--- a/.doc_gen/metadata/s3_metadata.yaml
+++ b/.doc_gen/metadata/s3_metadata.yaml
@@ -2952,6 +2952,14 @@ s3_Scenario_PresignedUrl:
- snippet_tags:
- s3.php.presigned_url.complete
- php.example_code.s3.service.S3Service
+ SAP ABAP:
+ versions:
+ - sdk_version: 1
+ github: sap-abap/services/s3
+ excerpts:
+ - description: Create presigned requests to GET S3 objects.
+ snippet_tags:
+ - s3.abapv1.s3_presigned_url_get
services:
s3: {}
s3_Scenario_ObjectVersioningUsage:
diff --git a/sap-abap/services/s3/README.md b/sap-abap/services/s3/README.md
index d8454a2bec8..bb0fd168e11 100644
--- a/sap-abap/services/s3/README.md
+++ b/sap-abap/services/s3/README.md
@@ -48,6 +48,13 @@ Code excerpts that show you how to call individual service functions.
- [ListObjectsV2](zcl_aws1_s3_actions.clas.abap#L197)
- [PutObject](zcl_aws1_s3_actions.clas.abap#L216)
+### Scenarios
+
+Code examples that show you how to accomplish a specific task by calling multiple
+functions within the same service.
+
+- [Create a presigned URL](zcl_aws1_s3_scenario.clas.abap)
+
@@ -79,6 +86,18 @@ This example shows you how to do the following:
+#### Create a presigned URL
+
+This example shows you how to create a presigned URL for Amazon S3 and upload an object.
+
+
+
+
+
+
+
+
+
### Tests
⚠ Running tests might result in charges to your AWS account.
diff --git a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.abap b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.abap
index 0857d599654..1921a5dc280 100644
--- a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.abap
+++ b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.abap
@@ -10,11 +10,25 @@ CLASS zcl_aws1_s3_scenario DEFINITION
METHODS getting_started_with_s3
IMPORTING
- !iv_bucket_name TYPE /aws1/s3_bucketname
- !iv_key TYPE /aws1/s3_objectkey
- !iv_copy_to_folder TYPE /aws1/s3_bucketname
+ !iv_bucket_name TYPE /aws1/s3_bucketname
+ !iv_key TYPE /aws1/s3_objectkey
+ !iv_copy_to_folder TYPE /aws1/s3_bucketname
EXPORTING
- !oo_result TYPE REF TO /aws1/cl_knsputrecordoutput .
+ !oo_result TYPE REF TO /aws1/cl_knsputrecordoutput
+ RAISING
+ /aws1/cx_rt_service_generic
+ /aws1/cx_rt_technical_generic
+ /aws1/cx_rt_no_auth_generic .
+ METHODS presigner_get
+ IMPORTING
+ !iv_bucket_name TYPE /aws1/s3_bucketname
+ !iv_key TYPE /aws1/s3_objectkey
+ RETURNING
+ VALUE(ov_url) TYPE string
+ RAISING
+ /aws1/cx_rt_service_generic
+ /aws1/cx_rt_technical_generic
+ /aws1/cx_rt_no_auth_generic .
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
@@ -140,4 +154,44 @@ CLASS ZCL_AWS1_S3_SCENARIO IMPLEMENTATION.
"snippet-end:[s3.abapv1.getting_started_with_s3]
ENDMETHOD.
+
+
+ METHOD presigner_get.
+ CONSTANTS cv_pfl TYPE /aws1/rt_profile_id VALUE 'ZCODE_DEMO'.
+
+ "snippet-start:[s3.abapv1.s3_presigned_url_get]
+ " iv_bucket_name is the bucket name
+ " iv_key is the object name like "myfile.txt"
+
+ DATA(lo_session) = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ DATA(lo_s3) = /aws1/cl_s3_factory=>create( lo_session ).
+
+ "Upload a nice Hello World file to an S3 bucket."
+ TRY.
+ DATA(lv_contents) = cl_abap_codepage=>convert_to( 'Hello, World' ).
+ lo_s3->putobject(
+ iv_bucket = iv_bucket_name
+ iv_key = iv_key
+ iv_body = lv_contents
+ iv_contenttype = 'text/plain' ).
+ MESSAGE 'Object uploaded to S3 bucket.' TYPE 'I'.
+ CATCH /aws1/cx_s3_nosuchbucket.
+ MESSAGE 'Bucket does not exist.' TYPE 'E'.
+ ENDTRY.
+
+ " now generate a presigned URL with a 600-second expiration
+ DATA(lo_presigner) = lo_s3->get_presigner( iv_expires_sec = 600 ).
+ " the presigner getobject() method has the same signature as
+ " lo_s3->getobject(), but it doesn't actually make the call.
+ " to the service. It just prepares a presigned URL for a future call
+ DATA(lo_presigned_req) = lo_presigner->getobject(
+ iv_bucket = iv_bucket_name
+ iv_key = iv_key ).
+
+ " You can provide this URL to a web page, user, email etc so they
+ " can retrieve the file. The URL will expire in 10 minutes.
+ ov_url = lo_presigned_req->get_url( ).
+ "snippet-end:[s3.abapv1.s3_presigned_url_get]
+
+ ENDMETHOD.
ENDCLASS.
diff --git a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.testclasses.abap b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.testclasses.abap
index a2f5cb9fc97..5ffd5c8e5f8 100644
--- a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.testclasses.abap
+++ b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.testclasses.abap
@@ -18,7 +18,7 @@ CLASS ltc_zcl_aws1_s3_scenario DEFINITION FOR TESTING DURATION SHORT RISK LEVEL
DATA ao_s3_scenario TYPE REF TO zcl_aws1_s3_scenario.
METHODS getting_started_scenario FOR TESTING RAISING /aws1/cx_rt_generic.
-
+ METHODS presigner_get_scenario FOR TESTING RAISING /aws1/cx_rt_generic cx_uuid_error.
METHODS setup RAISING /aws1/cx_rt_generic zcx_aws1_ex_generic.
METHODS teardown RAISING /aws1/cx_rt_generic zcx_aws1_ex_generic.
@@ -75,4 +75,39 @@ CLASS ltc_zcl_aws1_s3_scenario IMPLEMENTATION.
act = lv_found
msg = |Bucket { av_bucket } should have been deleted| ).
ENDMETHOD.
+
+ METHOD presigner_get_scenario.
+ " we don't show the customer the bucket creation in this scenario.
+ " So we'll create a separate bucket just for this scenario
+ DATA(lo_session) = /aws1/cl_rt_session_aws=>create( cv_pfl ).
+ DATA(lo_s3) = /aws1/cl_s3_factory=>create( lo_session ).
+
+ DATA(lv_region) = CONV /aws1/s3_bucketlocationcnstrnt( lo_session->get_region( ) ).
+ DATA lo_constraint TYPE REF TO /aws1/cl_s3_createbucketconf.
+ IF lv_region = 'us-east-1'.
+ CLEAR lo_constraint.
+ ELSE.
+ lo_constraint = NEW /aws1/cl_s3_createbucketconf( lv_region ).
+ ENDIF.
+
+ DATA(lv_uuid) = cl_system_uuid=>if_system_uuid_static~create_uuid_c32( ).
+ TRANSLATE lv_uuid TO LOWER CASE.
+ DATA(lv_bucket_name) = |sap-abap-s3-scenario-presigner-{ lv_uuid }|.
+
+ lo_s3->createbucket(
+ iv_bucket = lv_bucket_name
+ io_createbucketconfiguration = lo_constraint ).
+
+
+ DATA(lv_url) = ao_s3_scenario->presigner_get(
+ iv_bucket_name = lv_bucket_name
+ iv_key = cv_file ).
+ ASSERT lv_url IS NOT INITIAL.
+
+ " cleanup
+ lo_s3->deleteobject( iv_bucket = lv_bucket_name iv_key = cv_file ).
+ lo_s3->deletebucket( iv_bucket = lv_bucket_name ).
+
+ ENDMETHOD.
+
ENDCLASS.
diff --git a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.xml b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.xml
index 97af3930292..6bae44f2d78 100644
--- a/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.xml
+++ b/sap-abap/services/s3/zcl_aws1_s3_scenario.clas.xml
@@ -18,7 +18,56 @@
E
Getting started with Amazon S3 buckets and objects.
+
+ PRESIGNER_GET
+ E
+ Getting started with Amazon S3 buckets and objects.
+
+
+
+ GETTING_STARTED_WITH_S3
+ /AWS1/CX_RT_NO_AUTH_GENERIC
+ E
+ Generic lack of authorization
+
+
+ GETTING_STARTED_WITH_S3
+ /AWS1/CX_RT_SERVICE_GENERIC
+ E
+ Generic Service call error
+
+
+ GETTING_STARTED_WITH_S3
+ /AWS1/CX_RT_TECHNICAL_GENERIC
+ E
+ Technical errors
+
+
+ PRESIGNER_GET
+ /AWS1/CX_RT_NO_AUTH_GENERIC
+ E
+ Generic lack of authorization
+
+
+ PRESIGNER_GET
+ /AWS1/CX_RT_SERVICE_GENERIC
+ E
+ Generic Service call error
+
+
+ PRESIGNER_GET
+ /AWS1/CX_RT_TECHNICAL_GENERIC
+ E
+ Technical errors
+
+
+ PRESIGNER_GET
+ IV_KEY
+ E
+ Object Key
+
+