Error encountered while attempting to convert a Base-64 string into an image

I need help with sending a Highcharts chart as an image on ASP.NET button click. Here is what I am trying to accomplish:

To convert the chart into a base64 image, I am using the following code:

  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;

The next step involves taking the base64 image value, converting it to an image and attaching it to the email. Here is the code snippet:

 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);
 }

However, 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. "}

When I remove 'data:image/svg+xml;base64,' before converting it, the exception doesn't occur but the image doesn't appear. Can anyone suggest a solution?

Thank you

Answer №1

To remove the initial part of the string "data:image/svg+xml;base64," as it is not base64, only the remaining part should be considered. There is no requirement to utilize HttpUtility.UrlDecode in this scenario.

It is advisable to specify the TransferEncoding as Base64:

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

Nevertheless, using SVG in email comes with certain limitations and challenges. In such cases, opting for a different format like JPG or PNG may be more suitable. If you choose this path, a conversion library will be necessary to switch between formats.

Answer №2

Through extensive research, I finally found the solution to my problem. It turns out that not all client emails support data URI. If you're curious about Data URI support in major email client software, check out this resource.

I encountered issues when trying to open the mail from Outlook 2016, as it is not supported. However, when I opened it from hotmail.com, everything worked perfectly.

Here is the code snippet:

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);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Emptying the AnyChart (Javascript) container prior to generating new charts

I have been utilizing the anychart JavaScript library to generate a pie-chart from my data, which is dynamically pulled whenever a user modifies a dropdown selection. Below is the code snippet I am employing for this purpose: var stage = anychart.graph ...

The JObject parsing function unexpectedly outputs additional curly braces

I am encountering an issue with my variable projectData, which stores a valid JSON string in a database. Upon attempting the following: JObject obj = new JObject(); obj = JObject.Parse(projectData); Instead of the expected result: { "devices": ...

I am not receiving any results from the geocoder on Google maps

I am currently working on implementing the JS geocoding api but I keep encountering an error: Failed to load resource: net::ERR_BLOCKED_BY_CLIENT Despite having my api key activated. I have tried the following: Within HTML: <script src="{% stati ...

Dynamic rows in an Angular 2 Material data table

I'm currently working on dynamically adding rows to an Angular 2 Data Table ( https://material.angular.io/components/table/overview) by utilizing a service called "ListService". This service provides me with the columns ("meta.attributes") to be displ ...

Guide on passing a key as a parameter in the AFMultipartFormData of AFNetworking 3

Here is how my request is being sent: NSString *string = [NSString stringWithFormat:@"%@/API/Upload",BaseURLString]; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager setRequestSerializer:[AFHTTPRequestSerializer serializer] ...

Error: Unable to access the 'Result' property because it is undefined

I am encountering an issue while attempting to showcase database results, and the error message I'm receiving is: TypeError: Cannot read property 'Result' of undefined I am in the process of developing a Single Page Application with Angula ...

Seeking a blueprint for loading polymorphic objects efficiently

Can someone suggest an elegant approach for loading polymorphic objects? I have a base class and multiple derived classes that the base class is unaware of. The only information the base class has is a Type enum which indicates the specific subclass. cla ...

Beware of overwriting the first element in an array when creating it with a while loop in JavaScript or AppsScript

I am attempting to generate an array containing all dates within a specified time frame. To test this, I have chosen Feb 9 - Feb 13 as the date range. Ideally, the resulting array should display [Feb 9, Feb 10, Feb 11, Feb 12, Feb 13]. Upon revisiting an o ...

Is it possible to have a variable accessible to all pages within a view controller file?

Within my application, I have a viewController file that allows me to pass variables to the front end. However, there are certain variables that are required on each page. Rather than duplicating code for each page, is there a way to efficiently pass a var ...

Discovering the smallest, largest, and average values across all properties in an array of objects

Given an array of objects with varying values, the task is to determine the minimum, maximum, and average of the properties in that array. For example, consider the following array: const array = [{ "a": "-0.06", "b": "0.25", "c": "-0.96", ...

Is there a method to access the output of getStaticProps function from NextJS API routes?

Is there a method to compute and cache new data during build time that is essential for both the front-end and back-end API routes? I'm looking for a way to access the static properties generated by API routes at build time since the routes are access ...

How about conducting unit tests for a JSON formatter?

Currently, I am in the process of developing a library that has the ability to take a JSON string and format it based on a template and specification selected by the user. Lately, I have begun writing Unit Tests for this library and have encountered diffi ...

Shadows are displaying properly on a cube within Three.js, but they are not appearing on a JSON mesh

I'm having trouble getting my racecar to cast a shadow on the floor. While the cube is successfully casting a shadow, the imported json mesh object racecar is not. I'm wondering if this has something to do with the json file baking on the materia ...

Experiencing difficulties installing the MEAN stack

I've been attempting to set up the MEAN stack by following a tutorial on Bossable website. I'm using Webstorm and MongoDB for this installation. Unfortunately, I'm facing some issues and encountering errors. Every time I try to connect to l ...

I am experiencing an issue with my jQuery loop code not functioning properly when using the .each method within the loop

I am struggling with the following code. <input type="text" name="1" class = "inp<?=$p?>"> <input type="text" name="2" class = "inp<?=$p?>"> <input type="text" name="3" class = "inp<?=$p?>"> <input type="text" na ...

Tips for obtaining a JSON response from a RESTful API in AngularJS by utilizing the $resource service

I have been working on my AngularJS code, and although I am receiving a response in the console, I am having trouble storing it in an array or JSON format. angular.module('user', ['ngResource']). config(function($httpProvider){ $h ...

There was a problem encountered while trying to open the dbf file: The external table does not conform to

I am currently using this code snippet to import a dbf file. However, I encountered an error message: 'External table is not in expected format' if (ofdDBF.ShowDialog()==DialogResult.OK) { string connStr = @"Provider=Microsoft.Jet.OLED ...

I encountered an error while attempting to import a file into Firebase Storage

I've been struggling to upload files from Firebase Storage and encountering errors despite reading the documentation and various blogs on the topic. I'm looking for the most effective approach to resolve this issue. import { storage } from ' ...

Popup appears on incorrect page

As part of my app development project, I implemented a popover feature that opens when clicking on a label. Initially, this functioned smoothly within a tab navigation setup. However, after transitioning from tab modules to the app-routing module to displa ...

Is there a way to hold off passing props until after setState() has completed?

I wrote a function named renderLayers that iterates through each object in the filterState array and copies those with the checked property set to true. const [layers, setLayers] = useState([]); (...) const renderLayers = () => { const ne ...