We have a requirement to save a Datazen dashboard report to an image file.
The report will be hosted in an MVC view via an iframe. The underlying reports will be secured via active directory authentication within Datazen.
I was thinking I would use a WebBrowser control in a thread launched in STA mode. This kind of works but I get presented with the login screen when I try to view a url such as:
http://MyServerAddress/viewer/dashboard?dashboardguid=17EF844E-DEBE-4FE5-B22E-CD6F74A9E6C9
This is the code I have so far.
public ActionResult Save()
{
var url = "http://MyServerAddress/viewer/dashboard?dashboardguid=17EF844E-DEBE-4FE5-B22E-CD6F74A9E6C9";
FileContentResult result = null;
Bitmap bitmap = null;
var thread = new Thread(
() =>
{
bitmap = ExportUrlToImage(url, 1280, 1024);
});
thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
thread.Start();
thread.Join();
if (bitmap != null)
{
using (var memstream = new MemoryStream())
{
bitmap.Save(memstream, ImageFormat.Jpeg);
result = this.File(memstream.GetBuffer(), "image/jpeg");
}
}
return result;
}
private Bitmap ExportUrlToImage(string url, int width, int height)
{
// Load the webpage into a WebBrowser control
WebBrowser wb = new WebBrowser();
wb.ScrollBarsEnabled = false;
wb.ScriptErrorsSuppressed = true;
string hdr = "Authorization: Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("username" + ":" + "password")) + System.Environment.NewLine;
wb.Navigate(url, null, null, hdr);
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
// Set the size of the WebBrowser control
wb.Width = width;
wb.Height = height;
Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
wb.DrawToBitmap(bitmap, new System.Drawing.Rectangle(0, 0, wb.Width, wb.Height));
wb.Dispose();
return bitmap;
}
Wanted to see if I was on track and hadn't missed an alternative approach?
In the end we decided to use the following client library Html2Canvas
Need to be mindful of CORS issues so ensure the Datazen iframe is hosted on the same server / port etc as your web page.
There were issues rendering the entire page (i.e. parent page AND iframe content) so for that reason I just ended up exporting the iframe content only.
$(document).ready(function () {
$("#btnSave").click(function () {
// just render the body of the datazen iframe
var body = $("#iframe").contents().find('body');
html2canvas(body, {
allowTaint: true,
onrendered: function (canvas) {
// canvas is the final rendered <canvas> element
var myImage = canvas.toDataURL("image/png");
window.open(myImage);
}
})
});