Skip to main content

Oracle Apex - Upload Files to Amazon S3 Directly From Browser

This article is about uploading files from Oracle Apex to AWS S3. The files are directly uploaded to S3 without using any intermediate storage. The metadata is written to application DB to simplify further access. 


This includes setting an S3 bucket, Amazon Cognito Identity Pool, Configuring IAM, and configuring CORS. 

You will require bucket name, bucket region and pool id to access S3. Credentials are stored in DB and accessed using apex.server process while the user clicks the upload button.

Apex Tasks

Step#1 
Add AWS SDK in your application user interface details. Refer the attachment.


Step#2 
Create a PL/SQL dynamic region using below given code

htp.p('<div> <input type="file" id="fileUpload"> </div>');

Step#3 
Add the upload button and execute the javascript in dynamic action or set button action to "Redirect URL" and call the upload function using the link builder. I recommend using the second approach as there is a limit on characters in DA execute javascript. In this method, you can write a script in Function and Global Variable part of the page or in an external javascript file.

Step#4

You may modify the below snippet with your credentials to upload files to S3. Here, I'm using two apex server process viz., PREPARE_BUCKET, UPDATE_FILE_METADATA. The first is used to fetch AWS credentials from DB and later to write metadata in the application database. You may construct the bucketKey using your logic.

function uploadFile(){
    var spinner = apex.util.showSpinner();
    var files = document.getElementById('fileUpload').files;
    if (files.length>0) {
        apex.server.process("PREPARE_BUCKET", { 
        }, {
            success: function(pData) {
                 var bucketName = pData.bucket_param[0].p_bucket_name;
                 var bucketRegion = pData.bucket_param[0].p_bucket_region;
                 var IdentityPoolId = pData.bucket_param[0].p_ip;

                 AWS.config.update({
                                region: bucketRegion,
                                credentials: new AWS.CognitoIdentityCredentials({
                                IdentityPoolId: IdentityPoolId
                                })
                            });
                            var s3 = new AWS.S3({
                                apiVersion: '2006-03-01',
                                params: {Bucket: bucketName}
                        });
                //upload data
                
                    var file = files[0];
                    var fileName = file.name;
                    var bucketKey = 'folder1/folder2/'+file.name; //File Path
                    
                    // Use S3 ManagedUpload class as it supports multipart uploads
                      var upload = new AWS.S3.ManagedUpload({
                        params: {
                          Bucket: bucketName,
                          Key: bucketKey,
                          Body: file
                        }
                      });
                      var promise = upload.promise();
                      promise.then(
                        function(data) {                      
                          //insert metadata to application database
                          apex.server.process ( 
                              "UPDATE_FILE_METADATA"
                            ,   {   x01: apex.item("P94_APP_CODE").getValue()
                                ,   x02: apex.item("P94_BASE_DOC").getValue()
                                ,   x03: apex.item("P94_OBJECT").getValue()
                                ,   x04: apex.item("P94_OBJECT_PK").getValue()
                                ,   x05: file.name
                                ,   x06: file.size
                                ,   x07: file.type
                                ,   x08: bucketKey
                                }
                             , { dataType: 'text'
                             ,success: function(pData){
                                spinner.remove();
                                apex.event.trigger( "#attachments", "apexrefresh" );
                                apex.message.clearErrors();
                                apex.message.showPageSuccess( file.name+" uploaded successfully." );
                                $("#fileUpload").val('');
                            }
                             ,error: function( jqXHR, textStatus, errorThrown ) {
                                spinner.remove();
                                apex.message.clearErrors();
                                apex.message.showErrors([
                                  {
                                    type: apex.message.TYPE.ERROR,
                                    location: ["page"],
                                    message: "There was an error in uploading "+file.name,
                                    unsafe: false
                                  }
                                ]);
                              }
                            }
                            );
                        },
                        function(err) {
                            spinner.remove();
                            apex.message.clearErrors();
                            apex.message.showErrors([
                              {
                                type: apex.message.TYPE.ERROR,
                                location: ["page"],
                                message: "There was an error in uploading the file.",
                                unsafe: false
                              }
                            ]);
                        }
                      );
              
            },
            error: function( jqXHR, textStatus, errorThrown ) {
                spinner.remove();
                apex.message.clearErrors();
                apex.message.showErrors([
                  {
                    type: apex.message.TYPE.ERROR,
                    location: ["page"],
                    message: "There was an error in uploading the file",
                    unsafe: false
                  }
                ]);
            }
        }); 
    }else{   
        spinner.remove();
        apex.message.clearErrors();
        apex.message.showErrors([
          {
            type: apex.message.TYPE.ERROR,
            location: ["page"],
            message: "No files selected for upload.",
            unsafe: false
          }
        ]);
    }    
}



Comments

Popular posts from this blog

How to set Modal Dialog Title in Oracle APEX? JavaScript

 At times, the same modal dialog page is used to add as well as to edit a record. In such circumstances, a user-friendly title enhances the UX.  Updating non-modal dialog page title For a non-modal dialog, this is pretty straightforward. A substitution string can be used to dynamically set the title. For example, the page title in this scenario is set to Vendor display name. This is achieved by updating the title attribute. However, this approach will not work for modal dialogs. We can use javascript to update the modal dialog title. Updating Modal Dialog Title On page load, use a dynamic action to set the dialog title. .m-dialog-content CSS class is optional. This is used to avoid updating the title of the parent dialog in scenarios where a modal page opens another modal page. Output Edit Add