16.9.7 Storing an Uploaded File in Object Bucket

Upload a temporary file to an OCI object bucket and store its bucket file name in your table.

The PUT_BREAKROOM_PHOTO_TEMP_FILE procedure in the EBA_DEMO_WOODSHR_OCI package adds a temporary file from APEX_APPLICATION_TEMP_FILES to an object bucket. It uses the unique uploaded file name passed in the p_unique_file_name parameter to retrieve the BLOB content, MIME Type, and file name from APEX_APPLICATION_TEMP_FILES. In the Woods HR app, to ensure the file name is unique in the bucket, it prepends the primary key of the EBA_DEMO_EMP_BREAKROOM_PHOTO row passed in the p_breakroom_photo_id parameter. It calls procedure PUT_BUCKET_FILE to put the file name in the object bucket, then updates the EBA_DEMO_EMP_BREAKROOM_PHOTO row with the final bucket file name.

Tip:

Any pages that work with bucket-stored break room photos use the EMP_BREAKROOM_PHOTO_B view explained in Studying Supporting Tables and Views. It only contains the FILE_NAME column from the underlying EBA_DEMO_EMP_BREAKROOM_PHOTOS table, since the photo data and the MIME Type come from the file in the object bucket.

-- In package eba_demo_woodshr_oci
------------------------------------------------------------------------------- 
-- Put a breakroom photo temp file into an object bucket         
-------------------------------------------------------------------------------  
procedure put_breakroom_photo_temp_file( 
    p_bucket_name         in varchar2, 
    p_unique_file_name    in varchar2, 
    p_breakroom_photo_id  in number, 
    p_module_static_id    in varchar2 default 'bucket_objects', 
    p_operation_static_id in varchar2 default 'get_file') 
is 
    l_temp_image_blob blob; 
    l_file_name       varchar2(1000); 
begin 
    for j in (select blob_content, mime_type, filename 
                from apex_application_temp_files 
               where name = p_unique_file_name) 
    loop 
        if     j.blob_content is not null 
           and dbms_lob.getlength(j.blob_content) > 0 
        then 
            for k in (select file_name, mime_type 
                        from eba_demo_emp_breakroom_photos 
                       where id = p_breakroom_photo_id) 
            loop 
                l_file_name := p_breakroom_photo_id||'_'||j.filename; 
                put_bucket_file( 
                    p_bucket_name         => p_bucket_name, 
                    p_file_name           => l_file_name, 
                    p_mime_type           => j.mime_type, 
                    p_file_contents       => j.blob_content, 
                    p_module_static_id    => p_module_static_id, 
                    p_operation_static_id => p_operation_static_id); 
            end loop; 
            -- Record the filename the uploaded file gets in the bucket 
            update eba_demo_emp_breakroom_photos 
               set file_name = l_file_name 
             where id = p_breakroom_photo_id; 
        end if; 
    end loop; 
end put_breakroom_photo_temp_file; 

The PUT_BUCKET_FILE procedure calls private helper procedure BUCKET_URL_FOR explained in Serving Inline File from Object Bucket to get the absolute URL and web credential static id to use for the file "put" operation. It proceeds to set the Content-Type header to let the object bucket know the MIME Type of the file being stored, then uses MAKE_REST_REQUEST to perform an HTTP PUT operation with the absolute URL of the file. Notice that it passes the binary file contents as the value of the p_body_blob parameter.

Tip:

A REST Data Source operation does not currently support sending a binary request payload, so you need to use MAKE_REST_REQUEST with the p_body_blob parameter when the REST API to invoke expects the binary contents as the request body.

-- In package eba_demo_woodshr_oci
------------------------------------------------------------------------------- 
-- Put a file into an object bucket         
------------------------------------------------------------------------------- 
procedure put_bucket_file( 
    p_bucket_name         in varchar2, 
    p_file_name           in varchar2, 
    p_mime_type           in varchar2, 
    p_file_contents       in blob, 
    p_module_static_id    in varchar2 default 'bucket_objects', 
    p_operation_static_id in varchar2 default 'get_file') 
is 
    l_clob   clob; 
    l_url    varchar2(32767); 
    l_cred   varchar2(4000); 
begin 
    bucket_url_for( 
        p_module_static_id     => p_module_static_id, 
        p_operation_static_id  => p_operation_static_id, 
        p_bucket_name          => p_bucket_name, 
        p_file_name            => p_file_name, 
        p_credential_static_id => l_cred, 
        p_file_url             => l_url); 

    apex_web_service.set_request_headers( 
        p_name_01  => 'Content-Type', 
        p_value_01 => p_mime_type, 
        p_reset    => true); 

    l_clob := apex_web_service.make_rest_request( 
                p_credential_static_id => l_cred, 
                p_http_method          => 'PUT', 
                p_url                  => l_url, 
                p_body_blob            => p_file_contents); 

    if apex_web_service.g_status_code not in (200,201) then 
        raise_application_error(-20001, 
            'Upload failed: HTTP '||apex_web_service.g_status_code); 
    end if; 
end put_bucket_file;