Template handler uploading images
This document covers sample implementation for upload template POST handler uploading images on page submission or on demand using supporting dynamic action Upload Images on Demand. All examples uploads images to the plug-in sample application table UC_FROALA_SAMPLE_BLOBS. The difference between handlers is complexity of PL/SQL code, whether handler uses default query parameters, custom parameters or uses image checksum to secure display handler.
- Simple
- Default parameters
- Custom parameters
- Image checksum
- can be combined with handler displaying an image Simple
- can be combined with handler browsing images Simple
- doesn't use default parameters and the URL to displaying image handler (page item attribute Image GET URL) is hardcoded in the code
- can be combined with handler displaying an image Simple
- can be combined with handler browsing images Default Parametrs
- uses default parameters to fetch page item attribute Image GET URL from the plug-in access token
- can be combined with handler displaying an image Simple
- can be combined with handler browsing images Custom parameters
- uses default parameters to fetch page item attribute Image GET URL from the plug-in access token
- uses custom parameter
folder
to save additional information about image in the database - requires definining custom parameter using Initialization JavaScript Code and option imageUploadParams or using the supporting dynamic action plug-in Upload Parameters
- must be combined with handler displaying an image Image checksum
- must be combined with handler browsing images Image checksum
- uses default parameters to fetch page item attribute Image GET URL from the plug-in access token
- uses access token static function encode to create image checksum securing display handler using query parameter
- doesn't expose uploaded image id in the database
Requirements
The upload handler must meet the following requirements:
- must use POST method
- must be compilable at the run time
- must return 200 HTTP status code
- must print JSON describing uploaded image
Handler definition
- Simple
- Default parameters
- Custom parameters
- Image checksum
Attribute | Value |
---|---|
RESTful Service Module | A custom RESTservice |
Module Base Path | /customrest/ |
URI Template | upload-simple |
Full URL | https://example-domain.com/ords/workspacename/customrest/upload-simple |
Handler Method | POST |
Source Type | PL/SQL |
Mime Types Allowed | Not defined |
Attribute | Value |
---|---|
RESTful Service Module | A custom RESTservice |
Module Base Path | /customrest/ |
URI Template | upload-default |
Full URL | https://example-domain.com/ords/workspacename/customrest/upload-default |
Handler Method | POST |
Source Type | PL/SQL |
Mime Types Allowed | Not defined |
Attribute | Value |
---|---|
RESTful Service Module | A custom RESTservice |
Module Base Path | /customrest/ |
URI Template | upload-custom |
Full URL | https://example-domain.com/ords/workspacename/customrest/upload-custom |
Handler Method | POST |
Source Type | PL/SQL |
Mime Types Allowed | Not defined |
Attribute | Value |
---|---|
RESTful Service Module | A custom RESTservice |
Module Base Path | /customrest/ |
URI Template | upload-checksum |
Full URL | https://example-domain.com/ords/workspacename/customrest/upload-checksum |
Handler Method | POST |
Source Type | PL/SQL |
Mime Types Allowed | Not defined |
Handler parameters
The upload handler doesn't require registering any resource parameters as long as REST specific bind variable :status_code
is used to set request HTTP status.
Handler Source
- Simple
- Default parameters
- Custom parameters
- Image checksum
declare
v_image_blob blob := :body;
v_image_mime_type varchar2(4000) := :content_type;
v_image_link varchar2(4000);
v_file_id number;
/* without default parameters image filename is not available */
v_file_name varchar2(4000) := 'filename';
begin
insert into UC_FROALA_SAMPLE_BLOBS(
FILE_NAME,
FILE_CONTENT,
FILE_MIMETYPE,
SESSION_ID
) values(
v_file_name,
v_image_blob,
v_image_mime_type,
null
) returning ID into v_file_id;
/* The URL to RESTful service GET handler is hardcoded */
v_image_link := 'https://example-domain.com/ords/workspacename/customrest/display-simple/'||v_file_id;
/* print JSON to the browser buffer */
apex_json.open_object;
apex_json.write('link' , v_image_link, true);
apex_json.write('data-image-id', v_file_id , true);
apex_json.close_object;
/* set HTTP status code */
:status_code := 200;
exception
when others then
:status_code := 500;
apex_json.open_object;
apex_json.write('error', SQLERRM);
apex_json.close_object;
end;
declare
v_image_blob blob := :body;
v_image_mime_type varchar2(4000) := :content_type;
v_image_link varchar2(4000);
v_file_id number;
v_access_token uc_rte_access_token;
/* default query parameters computed on page load */
//highlight-next-line
v_param_accessToken varchar2(32767) := :accessToken;
//highlight-next-line
v_param_sessionId varchar2(32767) := :sessionId;
//highlight-next-line
v_param_filename varchar2(32767) := :filename;
begin
/* validate access token to check if it's authorised upload request */
//highlight-next-line
v_access_token := uc_rte_access_token.create_from_token( v_param_accessToken );
if v_access_token.is_valid = 0 then
raise_application_error(-20001, 'Invalid access token');
end if;
insert into UC_FROALA_SAMPLE_BLOBS(
FILE_NAME,
FILE_CONTENT,
FILE_MIMETYPE,
SESSION_ID
) values(
//highlight-next-line
v_param_filename,
v_image_blob,
v_image_mime_type,
//highlight-next-line
v_param_sessionId
) returning ID into v_file_id;
/* Use display URL defined for the plug-in instance */
v_image_link := v_access_token.url_get_image||v_file_id;
/* print JSON to the browser buffer */
apex_json.open_object;
apex_json.write('link' , v_image_link, true);
apex_json.write('data-image-id', v_file_id , true);
apex_json.close_object;
/* set HTTP status code */
:status_code := 200;
exception
when others then
if SQLCODE = -20001 then
:status_code := 403;
else
:status_code := 500;
apex_json.open_object;
apex_json.write('error', apex_string.format('While uploading an image, an unexpected error was raised: %s', SQLERRM));
apex_json.close_object;
end if;
end;
declare
v_image_blob blob := :body;
v_image_mime_type varchar2(4000) := :content_type;
v_image_link varchar2(4000);
v_file_id number;
v_access_token uc_rte_access_token;
/* default query parameters computed on page load */
v_param_accessToken varchar2(32767) := :accessToken;
v_param_sessionId varchar2(32767) := :sessionId;
v_param_filename varchar2(32767) := :filename;
/* custom query parameter "folder" */
//highlight-next-line
v_custom_folder varchar2(32767) := :folder;
begin
/* validate access token to check if it's authorised upload request */
v_access_token := uc_rte_access_token.create_from_token( v_param_accessToken );
if v_access_token.is_valid = 0 then
raise_application_error(-20001, 'Invalid access token');
end if;
insert into UC_FROALA_SAMPLE_BLOBS(
FILE_NAME,
FILE_CONTENT,
FILE_MIMETYPE,
SESSION_ID,
//highlight-next-line
FOLDER
) values(
v_param_filename,
v_image_blob,
v_image_mime_type,
v_param_sessionId,
//highlight-next-line
v_custom_folder
) returning ID into v_file_id;
/* Use display URL defined for the plug-in instance */
v_image_link := v_access_token.url_get_image||v_file_id;
/* print JSON to the browser buffer */
apex_json.open_object;
apex_json.write('link' , v_image_link, true);
apex_json.write('data-image-id', v_file_id , true);
apex_json.close_object;
/* set HTTP status code */
:status_code := 200;
exception
when others then
if SQLCODE = -20001 then
:status_code := 403;
else
:status_code := 500;
apex_json.open_object;
apex_json.write('error', apex_string.format('While uploading an image, an unexpected error was raised: %s', SQLERRM));
apex_json.close_object;
end if;
end;
declare
v_image_blob blob := :body;
v_image_mime_type varchar2(4000) := :content_type;
v_image_link varchar2(4000);
v_file_id number;
v_access_token uc_rte_access_token;
/* default query parameters computed on page load */
v_param_accessToken varchar2(32767) := :accessToken;
v_param_filename varchar2(32767) := :filename;
v_checksum varchar2(32767);
begin
/* validate access token to check if it's authorised upload request */
v_access_token := uc_rte_access_token.create_from_token( v_param_accessToken );
if v_access_token.is_valid = 0 then
raise_application_error(-20001, 'Invalid access token');
end if;
insert into UC_FROALA_SAMPLE_BLOBS(
FILE_NAME,
FILE_CONTENT,
FILE_MIMETYPE
) values(
v_param_filename,
v_image_blob,
v_image_mime_type
) returning ID into v_file_id;
// highlight-next-line
v_checksum := UC_RTE_ACCESS_TOKEN.encode( v_param_filename||','||v_file_id );
// highlight-next-line
v_image_link := v_access_token.url_get_image||v_param_filename||'?checksum='||v_checksum;
/* print JSON to the browser buffer */
apex_json.open_object;
apex_json.write('link' , v_image_link, true);
apex_json.write('data-image-id', v_file_id , true);
apex_json.close_object;
/* set HTTP status code */
:status_code := 200;
exception
when others then
if SQLCODE = -20001 then
:status_code := 403;
else
:status_code := 500;
apex_json.open_object;
apex_json.write('error', SQLERRM);
apex_json.close_object;
end if;
end;
Handler Output
When an image is saved in the database table, or any other service hosting images, the handler must print to the browser buffer JSON object containing URL displaying uplaoded image and unique image id.
Property | Type | Description |
---|---|---|
data-image-id | VARCHAR2 | The unique id identyfing uplaoded image. The uploaded image id is then stored in the plug-in session state |
link | VARCHAR2 | The uploaded image URL |
The example JSON might look like in the example below.
- Simple
- Default parameters
- Custom parameters
- Image checksum
{
"data-image-id": "1706",
"link": "https://example-domain.com/ords/workspacename/customrest/display/1706"
}
{
"data-image-id": "1706",
"link": "https://example-domain.com/ords/workspacename/customrest/display/1706"
}
{
"data-image-id": "1706",
"link": "https://example-domain.com/ords/workspacename/customrest/display/1706"
}
{
"data-image-id": "29662",
"link": "https://example-domain.com/ords/workspacename/customrest/display-checksum/pngaaa.com-4093606.png?checksum=B41B7A1987DE3A77E6E706C5112805E6713540B7C9F3116646C308428A82EBA9"
}
Link to uploaded image can include query parameters that can be used in display handler. See example source code Image checksum.
Error handling
The plug-in relies on HTTP status code set by the upload handler. Specifying HTTP status code results in display different errror message in the plug-in upload summary.
See sample code below presenting displaying custom error message using HTTP status code 500 and JSON printed to the browser buffer.
begin
...
exception
when others then
:status_code := 500;
apex_json.open_object;
apex_json.write('error', 'Error message to be displayed in the plug-in upload summary');
apex_json.close_object;
end;
403 Forbidden
The plug-in displays following message:
Uplaod handler: 403 Forbidden
404 Not Found
The plug-in displays following message:
Uplaod handler: 404 Not Found.
405 Method Not Allowed
The plug-in displays following message:
Uplaod handler: 405 Method Not Allowed
This status code can be assigned, when the plug-in page item attribute Image Upload URL reference RESTful service handler not implementing POST method.
500 Internal Sever Error
If handler result printed JSON with error
property, the plug-in display the error
property value. Otherwise the plug-in displays the following message:
Uplaod handler raised an error: 500 Internal Server Error (missin "error" property)
555 User Defined Error
This HTTP status code is set by ORDS REST when, the upload handler PL/SQL can't be executed when requested. The plug-in displays following message:
Uplaod handler raised error: 555 User Defined Error
In contrast to PL/SQL code attributes in page designer, the handler source attribute is not compiled when saving handler changes in SQL Workshop \ RESTful Services.
Other
If any other HTTP status code is the result of uplaod handler, the plug-in displays the following message:
Unexpected image upload error