I have set up iisnode and installed the highcharts-export-server in the directory I am hoping to be the server endpoint via:
1) I have copied an existing directory under C:\Program Files\iisnode\www to a new directory under the C:\Program Files\iisnode\www path in Windows (where the sample iisnode pages exist).
2) I have opened a command prompt in this new directory (as administrator) and run the following:
npm init (leaving all options as default/empty
npm install --save highcharts-export-server (and responded to the questions asked)
3) I have set up my endpoint file as hcexport.js and it contains:
var http = require('http');
var qs = require('querystring');
const exporter = require('highcharts-export-server');
http.createServer(function (request, res) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// 1e6 === 1 * Math.pow(10, 6) === 1 * 1000000 ~~~ 1MB
if (body.length > 1e6) {
// FLOOD ATTACK OR FAULTY CLIENT, NUKE REQUEST
request.connection.destroy();
}
});
request.on('end', function () {
var POST = qs.parse(body);
var extype = POST.type;
// use POST
console.log(POST);
exporter.initPool();
exporter.export(POST, function (err, exres) {
//The export result is now in exres.
//If the output is not PDF or SVG, it will be base64 encoded (res.data).
//If the output is a PDF or SVG, it will contain a filename (res.filename).
console.log(exres);
if (extype == 'image/png' || extype == 'image/jpeg') {
res.setHeader('Content-disposition', 'attachment; filename=' + exres.filename);
res.setHeader('Content-type', extype);
res.write(exres.filename);
res.end();
}
if (extype == 'image/svg+xml') {
res.setHeader('Content-disposition', 'attachment; filename=' + exres.filename);
res.setHeader('Content-type', extype);
res.write(exres.filename);
res.end();
}
if (extype == 'application/pdf') {
res.setHeader('Content-disposition', 'attachment; filename=' + exres.filename);
res.setHeader('Content-type', extype);
res.write(exres.filename);
res.end();
}
//Kill the pool when we're done with it, and exit the application
exporter.killPool();
process.exit(1);
});
});
}
}).listen(process.env.PORT);
I then created a sample chart (stock chart) that is representative of some of our data and chart options. I use the built-in chart export logic when a user clicks on a button to export the chart (we do not use the built-in button menu). This code looks like:
var chart = $('#' + chartid).highcharts();
var navigatorData = chart.get("highcharts-navigator-series").options.data;
var chartSeries = chart.userOptions.series;
chart.exportChart({
filename: 'test',
type: exportType,
scale: 1
}, {
title: {
text: graphHeader,
margin: marginSize
},
navigator: {
series: {
data: navigatorData
}
},
legend: {
y: -6
},
subtitle: {
y: 3,
text: graphFooter
},
chart: {
spacingBottom: 35,
shadow: false,
height: 1.1 * chart.chartHeight,
width: 800
},
series: chartSeries
});
When I click our button to export the attempt fails instantly with an error returned to the page that held the chart. In iisnode they provide a logging mechanism and this shows the contents of my POST request:
{ '------WebKitFormBoundaryaes0yytBA1i6RUkH\r\nContent-Disposition: form-data; name': '"filename"\r\n\r\ntest\r\n------WebKitFormBoundaryaes0yytBA1i6RUkH\r\nContent-Disposition: form-data; name="type"\r\n\r\nimage/png\r\n------WebKitFormBoundaryaes0yytBA1i6RUkH\r\nContent-Disposition: form-data; name="width"\r\n\r\n0\r\n------WebKitFormBoundaryaes0yytBA1i6RUkH\r\nContent-Disposition: form-data; name="scale"\r\n\r\n1\r\n------WebKitFormBoundaryaes0yytBA1i6RUkH\r\nContent-Disposition: form-data; name="svg"\r\n\r\nhttp://www.w3.org/2000/svg" width="800" height="550" viewBox="0 0 800 550">Created with Highstock 5.0.10....
And then a nice useful error message:
Thu Apr 20 2017 08:28:40 GMT-0400 (Eastern Daylight Time) [error] no input specified { contents of the POST }
How can I get the export server to return the chart image? What have I missed here?
I did another test using what should be sent in as a manual POST request following the instructions here. In this case I have the same node module code but my export looks like:
var exportRequest = {
svg: theChartSVG,
scale: 1,
filename: 'test',
type: exportType,
async: true
};
var exportUrl = 'http://myurl/node/exporter/';
$.post(exportUrl, exportRequest, function (data) {
var url = exportUrl + data;
console.log(url);
});
This is interesting for several reasons. One is that the code in the export module states that:
//The export result is now in exres. //If the output is not PDF or SVG, it will be base64 encoded (res.data). //If the output is a PDF or SVG, it will contain a filename (res.filename).
If I send up just the exres.data I get nothing. But if I send up exres.filename as the return and then build a URL string as you see on the success code set as var url = exportUrl + data;
I get a valid url with a filename.extension that I can click on and open and see the chart. But, I am unable to force a download of the image. The other interesting aspect of this is that the exres.filename sent back is not the input filename I sent to the export server. It is undefinedchart.png
for example. If I request an SVG for export I get no exres.filename sent up to the requester page - but I can got to the assumed URL and actually view the SVG image. What is happening?
via wergeld
No comments:
Post a Comment