16.9.5 Serving Inline File from Object Bucket

Serve an object bucket file inline using an APEX page.

You can create a page to serve inline object bucket images using the DOWNLOAD_BUCKET_FILE procedure. Just call it from a Pre-Rendering Invoke API page process, passing in the bucket file name to download inline. It calls the private helper procedure GET_BUCKET_FILE to retrieve the BLOB contents and MIME type of the bucket file and then downloads it using APEX_HTTP.DOWNLOAD. This page will be nearly identical to the ones explained in Serving Inline BLOB Images with a Page and Serving Inline Temp Images for Preview. The pages all differ only in the "download" procedure they call.

-- In package eba_demo_woodshr_oci
------------------------------------------------------------------------------- 
-- Download a file from an object bucket         
-------------------------------------------------------------------------------  
procedure download_bucket_file( 
    p_bucket_name         in varchar2, 
    p_file_name           in varchar2, 
    p_module_static_id    in varchar2 default 'bucket_objects', 
    p_operation_static_id in varchar2 default 'get_file') 
is 
    l_blob   blob; 
    l_mime   varchar2(4000); 
begin 
    get_bucket_file( 
        p_bucket_name         => p_bucket_name, 
        p_file_name           => p_file_name, 
        p_module_static_id    => p_module_static_id, 
        p_operation_static_id => p_operation_static_id, 
        p_file_contents       => l_blob, 
        p_mime_type           => l_mime); 

    apex_http.download( 
        p_blob         => l_blob, 
        p_content_type => l_mime, 
        p_is_inline    => true, 
        p_filename     => p_file_name); 
end download_bucket_file; 

The GET_BUCKET_FILE procedure calls private helper procedure BUCKET_URL_FOR to get the absolute URL and web credential static id to use for the file "get" operation. It sets the Accept and Accept-Encoding headers to let the object bucket know it wants to receive the binary content verbatim, without compression. It uses the MAKE_REST_REQUEST_B function to perform an HTTP GET operation with the absolute URL of the file, getting the binary file contents as the return value. Finally, it retrieves the MIME Type of the file by peeking at the Content-Type response header.

Tip:

A REST Data Source operation does not support a binary response, so use MAKE_REST_REQUEST_B to work with a REST API that returns a binary file.

-- In package eba_demo_woodshr_oci
------------------------------------------------------------------------------- 
-- Get file and mimetype from an object bucket file 
------------------------------------------------------------------------------- 
procedure get_bucket_file( 
    p_bucket_name         in varchar2, 
    p_file_name           in varchar2, 
    p_file_contents      out blob, 
    p_mime_type          out varchar2, 
    p_module_static_id    in varchar2 default 'bucket_objects', 
    p_operation_static_id in varchar2 default 'get_file') 
is 
    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  => 'Accept',          p_value_01 => '*/*', 
        p_name_02  => 'Accept-Encoding', p_value_02 => 'identity', 
        p_reset    => true); 

    p_file_contents := apex_web_service.make_rest_request_b( 
                p_credential_static_id => l_cred, 
                p_http_method          => 'GET', 
                p_url                  => l_url ); 

    if    apex_web_service.g_status_code <> 200 
       or p_file_contents is null 
       or dbms_lob.getlength(p_file_contents) = 0 
    then 
        raise_application_error(-20001, 
            'Download failed: HTTP '||apex_web_service.g_status_code); 
    end if; 

    p_mime_type := nvl(apex_web_service.get_request_header('Content-Type'), 
                    'application/octet-stream'); 
end get_bucket_file; 

The BUCKET_URL_FOR helper method queries application metadata for the REST Data Source operation whose static ID passed in p_operation_static_id. The p_module_static_id parameter value identifies the REST data source context for this lookup. The lets the REST Data Source definition itself supply the runtime code with the fully qualified URL and credential static ID without having to hard-code that information anywhere.

-- In package eba_demo_woodshr_oci
------------------------------------------------------------------------------- 
-- Return absolute URL of object bucket file using REST Data Source 
-- operation as a template 
------------------------------------------------------------------------------- 
procedure bucket_url_for( 
    p_module_static_id      in varchar2, 
    p_operation_static_id   in varchar2, 
    p_bucket_name           in varchar2, 
    p_file_name             in varchar2, 
    p_credential_static_id out varchar2, 
    p_file_url             out varchar2) 
is 
    c_app_id constant number := sys_context('APEX$SESSION','APP_ID'); 
begin 
    select replace( 
             replace(m.url_endpoint||o.url_pattern, ':filename', p_file_name), 
             ':bucketname', p_bucket_name), 
           m.credential_static_id 
      into p_file_url, p_credential_static_id 
      from apex_appl_web_src_operations o 
      join apex_appl_web_src_modules   m on o.module_id = m.module_id 
     where o.operation_static_id = p_operation_static_id 
       and m.module_static_id    = p_module_static_id 
       and o.application_id      = c_app_id; 
end bucket_url_for;