3

I am trying to send a Highcharts chart via image on ASP.NET button click. What I am trying to do is:

Convert the chart to base64 image, the code is the following :

  var chart = $('#main-content').highcharts();
    EXPORT_WIDTH = 1000;
    var render_width = EXPORT_WIDTH;
    var render_height = render_width * chart.chartHeight / chart.chartWidth;

    var svg = chart.getSVG({
        exporting: {
            sourceWidth: chart.chartWidth,
            sourceHeight: chart.chartHeight
        }
    });
    var contentToSend = 'data:image/svg+xml;base64,' + window.btoa(svg);
    var hdnField = document.getElementById("MainContent_ChartImage");
    hdnField.value = contentToSend;

Next step is taking the base64 image value, convert it to image an attach it to the mail, the code is:

 string textImage = ChartImage.Value;

 var imageData = Convert.FromBase64String(HttpUtility.UrlDecode(data));
 System.Net.Mail.LinkedResource res;
 AlternateView htmlView;
 using (MemoryStream ms = new MemoryStream(imageData, true))
 {
      ms.Position = 0;
      ms.Write(imageData, 0, imageData.Length);
      ms.Seek(0, SeekOrigin.Begin);
      res = new System.Net.Mail.LinkedResource(ms);
      htmlView = AlternateView.CreateAlternateViewFromString("<html><body><img src='cid:imageReport' width='100%' ></body></html>", null, "text/html");
      res.ContentId = "imageReport";
      htmlView.LinkedResources.Add(res);
      MailMessage mailMsg = new MailMessage();
      SmtpClient client = new SmtpClient();

      // ...

      mailMsg.IsBodyHtml = true;
      mailMsg.AlternateViews.Add(htmlView);
      client.Send(mailMsg);
 }

but the method Convert.FromBase64String throws an exception

{"The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters. "}

However when I remove 'data:image/svg+xml;base64,' then convert it, it doesn't throw an exception but the image will not appear. What should I do?

Thank you

Tamás Szabó
  • 1,388
  • 11
  • 23
ibrahim noureddine
  • 99
  • 1
  • 1
  • 11
  • 1
    I'm no expert on emails, but can't you just dump the base64 content straight into the email somewhere, rather than going via a memory stream? On the point of your question - how does the data get from client to server, you may find you don't need the `HttpUtility.UrlDecode` for instance - the framework may be handling it for you. – James Thorpe Jun 30 '17 at 12:59
  • i tried to put the base64 image as the image source , but it didn't work @JamesThorpe – ibrahim noureddine Jun 30 '17 at 13:02
  • 1
    Did you make sure it's a valid base64 string? – KSib Jun 30 '17 at 13:14
  • What email client are you using to test these? Are you sure it supports embedded svg? – tattarrattat Jun 30 '17 at 13:57
  • Apart from converting the image to base64 - you can use getSVG() method http://api.highcharts.com/highcharts/Chart.getSVG and use the svg image in emails. You can also use Highcharts exporting API to get the image (png, pdf, etc.). – morganfree Jul 02 '17 at 20:07
  • yes I did , I copied the text of base64 string to an online base64 to image converter , the image appeared @KSib – ibrahim noureddine Jul 10 '17 at 09:14
  • I am using the getSVG() method , but my purpose is to send it by mail.. So i am trying to encode the SVG to base64 string from the client side , then send it to the server side to convert the base64 string to an image and attach it to the mail. Exporting API will download the image locally on the client PC this is not my goal; @morganfree – ibrahim noureddine Jul 10 '17 at 09:17
  • You can send the svg as string to the server and attach svg to the email. By exporting API - I mean the API which is described at the bottom of the website I pasted - you can make a request from the serve with the chart options/svg string/etc. and receive the picture which can be attached to the email. – morganfree Jul 10 '17 at 16:01

2 Answers2

1

Get rid of the beginning part of the string: "data:image/svg+xml;base64," that part is not base64, just the remainder is. You don't need to use HttpUtility.UrlDecode either.

You should specify the TransferEncoding as Base64:

res.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;

However with all that said, there are some strong caveats to using SVG in email. So you may want to consider a different format such as JPG or PNG. If that's the route you take, you will need to use a library to convert formats.

John Bindel
  • 243
  • 2
  • 8
0

After many researches I found the solution , the main problem was that not all client email support data URI : What is Data URI support like in major email client software?

i was trying to open the mail from the outlook 2016 however it is not supported , when i opened from hotmail.com it worked..

the code is :

MailMessage mailMsg = new MailMessage();
SmtpClient client = new SmtpClient();
var imageData = Convert.FromBase64String(data);
var contentId = Guid.NewGuid().ToString();
var linkedResource = new LinkedResource(new MemoryStream(imageData), "image/svg+xml");
linkedResource.ContentId = contentId;
linkedResource.TransferEncoding = TransferEncoding.Base64;
var body = string.Format("<img src=\"cid:{0}\" />", contentId);
var htmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
 htmlView.LinkedResources.Add(linkedResource);
 mailMsg.AlternateViews.Add(htmlView);
ibrahim noureddine
  • 99
  • 1
  • 1
  • 11