Saving AnyChart 6 Charts as Images in Oracle APEX September 2nd, 2015 by Timothy Loginov

NOTE: This article tells how to set up the script in Oracle APEX and doesn’t affect AnyChart customers who use AnyChart outside of Oracle APEX.

Oracle Application Express is a web-based application development tool integrated with all editions of Oracle Database. It enables users with limited programming skills to easily develop secure web applications that run inside their Oracle Database, and scale to support tens, hundreds, or thousands of users.

Since Oracle Application Express Release 3.0, AnyChart is used as a charting engine (you can read about this in a success story: Oracle Chooses AnyChart Solution for Latest Release of Oracle® Application Express).

One of the nice features available in AnyChart since version 4.1.0 is the ability to save a Flash chart as an image – in order to make it possible, we have to use a server-side script, which is hosted on the AnyChart.Com site by default (read more about saving charts as images in AnyChart 6).

Federico Bonifazi from Geko Sistemi Informativi s.r.l. shared a solution that allows to save charts as images on the server side. We are very thankful for that and present it here for anyone who wants to do the same. This tutorial is very basic and is not a ready-to-go solution, but it gives the general idea, so you can use it to break ground on your project.

This configuration in based on Oracle Standard Edition on a Linux server, Oracle Rest and Tomcat are used.

1. Things to do in an Oracle APEX page

1.1. Add the following to the html header of the page:

<script type="text/javascript" src="/i/flashchart/anychart_6/js/AnyChart.js"></script>
<script type="text/javascript" language="JavaScript">
//<![CDATA[

AnyChart.swfFile = "/i/flashchart/anychart_6/swf/OracleAnyChart.swf";

function makeMultipartFormDataPostRequest(path, params) {
var xmlhttp = false;
var formData = new FormData();

if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
try {
xmlhttp = new XMLHttpRequest();
} catch (e) {
xmlhttp=false;
}
}

if (!xmlhttp && window.createRequest) {
try {
xmlhttp = window.createRequest();
}catch (e) {
xmlhttp=false;
}
}
xmlhttp.open('POST', path, false);
for (var propName in params) {
formData.append(propName, params[propName]);
}
return xmlhttp.send(formData);
}

function saveChartAsImage(chartName, chart) {
var requestData = {};
requestData['sessione'] = '&SESSION.';
requestData['imgName'] = chartName;
requestData['imgType'] = 'png';
requestData['imgDesc'] = 'nn';
requestData['imgData'] = chart.getPNG();

var path = makeMultipartFormDataPostRequest('http://localhost:8080/apex/report/saveImage/saveChart', requestData);
}
//]]>
</script>

1.2. Create a Flash chart:

<div id="report">
<div id="chart_container1"></div>
<script type="text/javascript" language="javascript">

var chart = new AnyChart();
chart.setXMLData($v('P205_CHARTO1_XML'));

chart.addEventListener("draw", function() {
saveChartAsImage("chart1", chart);
});

chart.write("chart_container1");
</script>
</div>

P205_CHART1_XML is hidden and filled with the dynamic content based on a query.

2. RestFull Service

2. Create a RestFull Service:
On Oracle APEX main page -> SQL Workshop -> RESTful services

RESTful Service Module: report
URI Prefix: saveImage/

2.1. then create
RESTful Service Module: report
URI Template: saveChart

2.2. Create POST Handler with PL/SQL code:

begin
:status := saveBase64toBlob
(
pSession => :session,
pImgName => :imgName,
pImgType => :imgType,
pImgDesc => :imgDesc,
pImgData => :imgData
);
end;

3.Saving the image to a table

saveBase64toBlob converts the base64 png to a blob and into the tbl_image:

function saveBase64toBlob
(
pSession varchar2,
pImgName varchar2,
pImgType varchar2,
pImgDesc varchar2,
pImgData clob
) return integer
is
retVal integer;
l_clob clob;
l_blob blob;
l_offset number;
v_buffer_size binary_integer := 48;
v_buffer_varchar varchar2(48);
v_buffer_raw raw(48);

begin
-- initialize
dbms_lob.createtemporary(l_blob, true);
l_offset := 1;
retVal := 0;

-- remove CRLF
l_clob := REPLACE(pImgData, chr(10), '');
l_clob := REPLACE(l_clob, chr(13), '');

for i in 1 .. ceil(dbms_lob.getlength(l_clob) / v_buffer_size)
loop
dbms_lob.read(l_clob, v_buffer_size, l_offset, v_buffer_varchar);
v_buffer_raw := utl_raw.cast_to_raw(v_buffer_varchar);
v_buffer_raw := utl_encode.base64_decode(v_buffer_raw);
dbms_lob.writeappend(l_blob, utl_raw.length(v_buffer_raw), v_buffer_raw);
l_offset := l_offset + v_buffer_size;
end loop;

insert into tbl_image
(
session,
img_name,
img_type,
img_desc,
img_data,
data_ora
)
values
(
pSession,
pImgName,
pImgType,
pImgDesc,
l_blob,
sysdate
);
commit;
return retVal;
end saveBase64toBlob;


Comments (1)

*