En nuestro blog anterior vimos como configurar la cámara de nuestro dispositivo para activar la cámara y/o capturar una imagen.
En este blog agregaremos una función adicional, que nos permita guarda dicha imagen en una tabla.
Lo primero que usaremos es una función JS adicional:
Parte importante es el envió de la imagen en base64.
function savePhotoInServer(){
const dataUrl = canvas.toDataURL('image/png');
const mimeType = dataUrl.substring(5, dataUrl.indexOf(';'));
// Convertir el canvas a Blob para envío
canvas.toBlob(function (blob) {
const reader = new FileReader();
reader.onloadend = function () {
const base64data = reader.result.split(',')[1]; // Obtener solo la parte de base64
// Llamada Ajax al proceso PL/SQL en APEX
apex.server.process('SAVE_PHOTO', {
f01: base64data // Enviar base64
, x02: mimeType // Enviar el MIME type
}, {
success: function (pData) {
console.log('Foto guardada exitosamente:', pData);
apex.region("ir_list_of_photos").refresh(); // Refrescar región con las fotos
},
error: function (jqXHR, textStatus, errorThrown) {
console.log('Error al guardar la foto:', textStatus, errorThrown);
}
});
};
reader.readAsDataURL(blob);
}, 'image/png');
}
Este código se tendrá que agregar en donde tenemos las demás funciones, para esta demo esta a nivel de página.

Ahora crearemos un proceso Ajax el cual tendrá el nombre de SAVE_PHOTO lo cual servirá para recibir la imagen en base64 y guardarla en la base de datos.
declare
l_blob blob;
l_base64 clob; -- recibe el base64 desde javascript
l_full_base64 clob; -- recibe el base64 desde javascript
l_mime_type varchar2(500) := apex_application.g_x02; -- mime type
l_length number;
begin
-- Comprobar la longitud del CLOB recibido
l_length := dbms_lob.getlength(l_base64);
if l_length = 0 then
raise_application_error(-20002, 'Error: El base64 está vacío.');
elsif l_length > 32767 then
raise_application_error(-20003, 'Error: El base64 es demasiado grande para procesar.');
end if;
-- Unir todos los fragmentos de APEX_APPLICATION.G_F01 en un solo CLOB
for i in 1 .. apex_application.g_f01.count loop
l_full_base64 := l_full_base64 || apex_application.g_f01(i);
end loop;
-- Remover el prefijo 'data:image/png;base64,' si existe
if instr(l_full_base64, ',') > 0 then
l_full_base64 := substr(l_full_base64, instr(l_full_base64, ',') + 1);
end if;
-- Decodificar el CLOB base64 a un BLOB
l_blob := apex_web_service.clobbase642blob(l_full_base64);
-- Guardar el BLOB en una tabla (ejemplo)
begin
insert
into photos_table(
photo_blob
, mime_type
)
values (l_blob
, l_mime_type
);
exception
when others then
raise_application_error(-20003, 'Error al insertar en la base de datos: ' || sqlerrm);
END;
apex_json.open_object;
apex_json.write('success',true);
apex_json.write('l_length',l_length);
apex_json.close_object;
exception
when others then
apex_json.open_object;
apex_json.write('success',false);
apex_json.write('error_msg',sqlerrm);
apex_json.close_object;
end;
Agregaremos un botón que tome la foto y guarde.
Incluimos las llamadas JavaScript a las funciones que creamos.
takePhotoButton();
savePhotoInServer();

Creación de tabla demo:
create table photos_table
(
"id" number generated by default on null as identity minvalue 1 maxvalue 9999999999999999999999999999 increment by 1 start with 1,
"photo_blob" blob,
"description" number,
"created_by" varchar2(60) default coalesce(
sys_context('apex$session','app_user')
, regexp_substr(sys_context('userenv','client_identifier'),'^[^:]*')
, sys_context('userenv','session_user')
) not null enable,
"created_on" date default localtimestamp not null enable,
"last_updated_by" varchar2(60),
"last_updated_on" date,
"mime_type" varchar2(4000),
constraint "photos_table_pk" primary key ("id")
using index enable
) ;
