Displaying Images in Oracle APEX Using (Oracle Cloud Infrastructure) OCI Object Storage

Displaying Images in Oracle APEX Using (Oracle Cloud Infrastructure) OCI Object Storage

In modern Oracle APEX applications, storing images inside database tables is rarely the best option.

OCI Object Storage gives you scalability, better performance, and lower cost.

This article explains how to display images in Oracle APEX using only OCI Object Storage, covering:

Secure image access

Pre-Authenticated Requests (PAR)

Friendly URLs

Performance and caching

A complete working flow

Why OCI Object Storage for Images

OCI Object Storage is ideal for images because:

No database size growth

Built for large binary files

Secure by default

Works cleanly with APEX and ORDS

Supports time-bound access via PAR

OCI does not allow public access by default, which is good.

It forces you to be explicit about how images are exposed.

Two Correct Ways to Display OCI Images in APEX

There are only two production-safe approaches.

1. APEX Proxy (Secure)

Browser → APEX → OCI Object Storage

Image fetched by APEX using credentials

Streamed to browser

Fully session-controlled

2. Pre-Authenticated Request (PAR) (Fast)

Browser → OCI Object Storage

Temporary public URL

No APEX load

Best for galleries and thumbnails

We’ll cover both, starting with PAR.

Full OCI PAR Generation Code (PL/SQL)

This function generates a browser-ready PAR URL for a single object.

What it does

Creates an object-level PAR

Sets expiry in hours

Returns a direct URL usable in <img src>

PL/SQL Function

CREATE OR REPLACE FUNCTION get_object_par_url (
in_region IN VARCHAR2, — ap-mumbai-1
in_namespace IN VARCHAR2, — OCI namespace
in_bucket_name IN VARCHAR2, — bucket name
in_object_name IN VARCHAR2, — images/product1.jpg
in_expiry_hours IN NUMBER DEFAULT 24
) RETURN VARCHAR2
IS
l_response CLOB;
l_access_uri VARCHAR2(4000);
l_expiry_ts VARCHAR2(50);
BEGIN
l_expiry_ts :=
TO_CHAR(
SYSTIMESTAMP AT TIME ZONE ‘UTC’
+ NUMTODSINTERVAL(in_expiry_hours, ‘HOUR’),
‘YYYY-MM-DD”T”HH24:MI:SS”Z”‘
);

l_response :=
apex_web_service.make_rest_request(
p_url => ‘https://objectstorage.’ || in_region ||
‘.oraclecloud.com/n/’ || in_namespace ||
‘/b/’ || in_bucket_name || ‘/p/’,
p_http_method => ‘POST’,
p_body => ‘{
“name”:”img_par_’ || DBMS_RANDOM.STRING(‘X’, 8) || ‘”,
“accessType”:”ObjectRead”,
“objectName”:”‘ || in_object_name || ‘”,
“timeExpires”:”‘ || l_expiry_ts || ‘”
}’
);

l_access_uri := json_value(l_response, ‘$.accessUri’);

RETURN ‘https://objectstorage.’ || in_region ||
‘.oraclecloud.com’ || l_access_uri;
END;
/

Using PAR in APEX

Generate URL in SQL

SELECT get_object_par_url(
‘ap-mumbai-1’,
‘a78hhjasl9djjkmz’,
‘product-images’,
‘products/p1001.jpg’,
6
) AS image_url
FROM dual;

Display in APEX

<img src=”#IMAGE_URL#” alt=”Product Image” loading=”lazy”>

#IMAGE_URL# is the URL placeholder

This is:

Fast

CDN-friendly

Perfect for cards, galleries, sliders

Secure Approach: Proxy OCI Images Through APEX

Direct URL is restricted for security.

Use this when:

Images are sensitive

Access depends on user role

You don’t want public URLs

On-Demand Application Process (APEX)

Create an Application Process named GET_OBJECT_FILE.

DECLARE
l_blob BLOB;
l_mime_type VARCHAR2(100);
BEGIN
l_blob := apex_web_service.make_rest_request_b(
p_url => :P0_OBJECT_URL,
p_http_method => ‘GET’
);

l_mime_type := apex_util.get_mime_type(:P0_FILE_NAME);

owa_util.mime_header(l_mime_type, FALSE);
htp.p(‘Content-Disposition: inline; filename=”‘ || :P0_FILE_NAME || ‘”‘);
owa_util.http_header_close;

wpg_docload.download_file(l_blob);
apex_application.stop_apex_engine;
END;

Generate Friendly URL

APEX_PAGE.GET_URL(
p_page => 0,
p_request => ‘APPLICATION_PROCESS=GET_OBJECT_FILE’,
p_items => ‘P0_OBJECT_URL,P0_FILE_NAME’,
p_values => object_url || ‘,’ || file_name
)

Use in HTML

<img src=”#IMAGE_URL#” alt=”Secure Image”>

Complete APEX + OCI Demo Flow

Here’s the end-to-end flow most real apps use.

Images uploaded to OCI bucket

Image paths stored in table (only metadata)

APEX page queries image paths

For each image:

Generate PAR (external users)

OR proxy via APEX (internal users)

Browser displays image

Image Caching Strategy (Very Important)

Without caching, image pages will feel slow.

For PAR URLs

OCI already supports HTTP caching

Keep PAR expiry ≥ image cache lifetime

Use browser caching

<img src=”PAR_URL” loading=”lazy”>

Best for:

Product images

Thumbnails

Public galleries

For APEX-proxied Images

Add cache headers:

htp.p(‘Cache-Control: private, max-age=3600’);
htp.p(‘Pragma: cache’);

This allows:

Browser caching

Reduced APEX load

Faster page rendering

Works perfectly with:

PAR URLs

APEX proxy URLs

Normal APEX pages

Potential errors:

BucketNotFound

Either the bucket named <bucket_name> does not exist in the namespace <namespace> or you are not authorized to access it

Final Recommendation

Use this rule:

Internal or sensitive images → APEX proxy

Public or high-traffic images → PAR

OCI Object Storage + APEX works extremely well when used correctly.

The post Displaying Images in Oracle APEX Using (Oracle Cloud Infrastructure) OCI Object Storage appeared first on Ontoor blogs.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *