APEX: Viewing Images and Videos from OCI Object Storage
I’m not going to answer this question as many of the examples and samples that explore beyond the simple UI calls, seem to involve some level of earnest coding and I’m no developer, so this .. this is not going to be pretty.
About this Post
Somethings in life are easy, simple, quick to understand and even quicker to drop onto a page, others are imagined to be. This article shares a solution that may be out there but I’ve lacked the endurance and skill to find.
This should be easy and there are many examples of accomplishing parts of this process but not a complete one.
I need to show embedded media that is stored on OCI Object Storage, that’s it.
Why is this even a discussion point?
Accessing Object Storage is different. There are many articles, books, discussions on the differences but for me the most poignant is unlike with file storage, you must use an Application Programming Interface (API) to access and manage objects.
OCI APIs typically require Authentication and some granted privileges or Authorisation.
Objects could be stored for Public access but not typical in enterprise environments. Although HTTP protocols and methods are used to manage the objects, the Object Storage service is not a Web or File Server, serving up its content to just anyone.
So, we must consume the API, retrieve our prized object in order to use it in our applications.
APEX and OCI Object Storage
APEX’s more recent releases offer Managing Static Application Files in Remote Storage and there are many posts on leveraging OCI Object Storage and even a LiveLab with step by step on how to Use Object Storage to Store Files in an APEX Application.
The Better File Storage in Oracle Cloud blog post is probably one of the most view, copied and reposted and it all lovely until you need to upload, download or delete an object.
I am hoping that after reading or following the above, you are well on your way to uploading / downloading objects using the PL/SQL Web_Service_Request Package.
The main call of interest is
apex_web_service.make_rest_request_b(
p_url => L_IMAGE_URL,
p_http_method => 'GET',
p_credential_static_id => L_APEX_WEB_CREDENTIAL
)
Embedding and Displaying Media Objects
Media in APEX is typically stored as a BLOB, having components to display its contents. The section on Understanding BLOB Support in Forms and Reports describes the declarative BLOB support to upload files in forms, and download or display files in reports.
By default, BLOB
columns do not display in a report. Reports that include a BLOB
column will display the text [unsupported data type]
for the column. A report can include a download link to retrieve the object.
If the BLOB you are working with is an image, you can display it in a report using the type Display Image on a numeric column that calculates the size and if the length is 0, the BLOB is NULL and no image is displayed.
If the content is stored elsewhere then either URL or in the case of OCI Object Storage an API request is required.
What is available OOTB?
The Cards & Content Row components both allow image display, with the Card component supporting declarative attributes for the Image URLs, URL and BLOB columns.
Classic Reports have the Display Image type for columns.
The Display Image type is also supported by APEX Form region
Displaying Image BLOB
Using the Components above and the PL/SQL API APEX_WEB_SERVICE.REST_REQUEST_B we are able to display image files stored on Object Storage.
Sample Table: MEDIA
create table MEDIA (
id number generated by default on null as identity
constraint aicd_media_id_pk primary key,
filename varchar2(4000 char),
url varchar2(4000 char),
mime_type varchar2(4000 char)
);
Page Region: Images
Type => Cards
Source: Type => SQL Query
SELECT
ID, FILENAME, MIME_TYPE,
apex_web_service.make_rest_request_b(
p_url => URL,
p_http_method => 'GET',
p_credential_static_id => :G_APEX_WEB_CREDENTIAL
) AS IMAGE
FROM MEDIA
Region: Attributes
Card: Primary Key => ID
Media: Source => BLOB Column
Media: BLOB Column => IMAGE
BLOB Attributes
- Mime Type Column => MIME_TYPE
Supported Image file types should be loaded.
Displaying Video BLOB
As of release 24.1.1, APEX supports images declaratively but to view any other media or content object some advanced formatting is required.
HTML as a core web technology provides tags for video content and its source. Extending this a bit further with data URIs I am able to embed any kind of data as long as I specify its mime type.
I have chosen to base64 encode my content and leverage the data URI format for the video source.
SELECT
ID, FILENAME, MIME_TYPE,
'<video controls>
<source src="data:'|| MIME_TYPE || ';base64,' || APEX_WEB_SERVICE.BLOB2CLOBBASE64(apex_web_service.make_rest_request_b(
p_url => URL,
p_http_method => 'GET',
p_credential_static_id => :G_APEX_WEB_CREDENTIAL
))
||'" type="' || MIME_TYPE|| '">
Sorry, your browser does not support the video tag.
</video>' AS VIDEO
FROM MEDIA
Apply the Raw formatting by selecting Advanced Formatting for the Media attribute with the RAW
escape filter to preserve the original item value and does not escape characters.
Something similar can be done for Page Forms using the Legacy PL/SQL Dynamic Content type.
This would require the blob content to be in a page item, so just remove the html tag when creating the form region.
SELECT
ID, FILENAME, MIME_TYPE,
apex_web_service.make_rest_request_b(
p_url => URL,
p_http_method => 'GET',
p_credential_static_id => :G_APEX_WEB_CREDENTIAL
) AS VIDEO
FROM MEDIA
Initialise the Form Region and then reference the Page Item when using the APEX_UTIL.GET_BLOB_FILE_SRC in the PL/SQL Code.
For example for Page 103 the Form Region the Page Items would be P103_ID for the ID, P103_VIDEO for the BLOB Content and P103_MIME_TYPE for the MIME_TYPE columns.
htp.p('<video controls width="320" height="240" autoplay>
<source src="'||apex_util.get_blob_file_src ('P103_VIDEO',:P103_ID,
p_content_disposition => 'inline')
||'" type="' || :P103_MIME_TYPE|| '">
Sorry, your browser does not support the video tag.
</video>');
Conclusion
Combining well documented techniques for APEX, PL/SQL and HTML we can view content stored on OCI Object Storage.
In this example, my use cases, I was able to embed both image and video content requested via the API source.
Would I recommend this?
Object size and network performance are the main concerns for implementing such a solution. Each object has to be requested from the object storage solution and considering the length of time it took to upload it there in the first instance, should give you an indicator how the download would compare.
For a single video, perhaps the app user will be fine or there will be ways to start streaming the object content, which I’ve not explored. Multiple medium to large video files … hopefully during your tests you will understand my concern.
Arguably getting this from the local database would be much faster if streaming is not an option.
Images, so far, no complaints on performance but these have been relatively small in contrast to the videos that I tested.
Legacy Components
In the last form based example I used the legacy PL/SQL Dynamic Content component. I can not give you any recommendations on using this component and hope there will be a replacement component support in the future.
Subscribe to my newsletter
Read articles from Sydney Nurse directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Sydney Nurse
Sydney Nurse
I work with software but it does not define me and my constant is change and I live a life of evolution. Learning, adapting, forgetting, re-learning, repeating I am not a Developer, I simply use software tools to solve interesting challenges and implement different use cases.