Convert from a DataUrl to an Image in C# and write a file with the bytes
Solution 1
As @SLaks mentioned I didn't need a MemoryStream, the problem with my code was the path and the filename for further help this is the working code:
if (newItem.FieldType == FormFieldType.Signature)
{
if (newItem.ItemValue != null)
{
//string completeImageName = Auth.host + "/" + li[i];
string path;
string filename;
string stringName = newItem.ItemValue;
var base64Data = Regex.Match(stringName, @"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
//filename = Path.Combine(path, base64Data.Replace(@"/", string.Empty));
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
string fileName = "Sn" + milliseconds.ToString() + ".PNG";
filename = Path.Combine(path, fileName);
if (!File.Exists(filename))
{
//using (var stream = new MemoryStream(binData))
//{
File.WriteAllBytes(filename, binData);
//}
}
newItem.ItemValue = filename;
}
}
App.Database.SaveReportItem(newItem);
And the image showed:
Solution 2
I just cleaned Mario's code and fine tuned regex:
public string SaveDataUrlToFile(string dataUrl, string savePath)
{
var matchGroups = Regex.Match(dataUrl, @"^data:((?<type>[\w\/]+))?;base64,(?<data>.+)$").Groups;
var base64Data = matchGroups["data"].Value;
var binData = Convert.FromBase64String(base64Data);
System.IO.File.WriteAllBytes(savePath, binData);
return savePath;
}
Related videos on Youtube
Mario Galván
I am Mexican Mobile developer and Xamarin enthusiast! follow me on twitter: @MayitoGalvan
Updated on June 15, 2022Comments
-
Mario Galván almost 2 years
Hello I have signature like this:
which is encoded to a DataUrl specifically this string:
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAADICAYAAADGFbfiAAAYlElEQVR4Xu2dC8w1R1nHQSCIgIKVGLmoiLciFwUs... (long string)"
What i want to do is Convert this DataUrl to an PNG Image, and save the image to the device, this is what i am doing so far:
if (newItem.FieldType == FormFieldType.Signature) { if (newItem.ItemValue != null) { //string completeImageName = Auth.host + "/" + li[i]; string path; string filename; string stringName = newItem.ItemValue; var base64Data = Regex.Match(stringName, @"data:image/(?<type>.+?),(?<data>.+)").Groups["data"].Value; var binData = Convert.FromBase64String(base64Data); path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); filename = Path.Combine(path, base64Data); if (!File.Exists(filename)) { using (var stream = new MemoryStream(binData)) { //Code crashing here-------------------------- File.WriteAllBytes(filename, binData); } } newItem.ItemValue = filename; } } App.Database.SaveReportItem(newItem);
But my code is making my application to crash specifically in this line:
File.WriteAllBytes(filename, binData);
The sample I am using as reference (Link) is using a PictureBox but with Xamarin there is no use of a pictureBox.
Any Ideas?
-
SLaks over 9 yearsWhat error do you get?
-
SLaks over 9 yearsWhy are you creating a MemoryStream?
-
Jason over 9 yearsIs it crashing on iOS or Android? And, ask SLaks asked, why open a stream and not use it? Are you sure your filename is getting set to a valid value?
-
Mario Galván over 9 yearsLooking at the output, (Using Android) this is the error let me change the path "Could not find a part of the path "/data/data/"
-
Jason over 9 yearswhat are the values of path and filename? It sounds like you are not building a valid path.
-
Mario Galván over 9 yearsYou are exactly right I am now using this:
filename = Path.Combine(path, base64Data.Replace(@"/", string.Empty));
but now my path its too long I am going to use the current time in miliseconds to create the file name. -
Fran_gg7 over 8 yearsHi friend, how did you made that control in Xamarin.Forms? I just need to implemente a tactile signature and then send it to server as image in base64. Thanks, wainting for your response.
-
Mario Galván over 8 yearsTo implement the signature: forums.xamarin.com/discussion/comment/176118#Comment_176118 but for sending the base64 image I haven't done that yet, hope this helps.
-
dave317 over 7 yearsHow did you make this work in C#? WHen I try and use File.WriteAllBytes, it is looking for 3 string arguments....
-
Mario Galván over 7 years@dave317 are you using a PCL or a Shared project? and File.WriteAllBytes is from System.IO: developer.xamarin.com/api/member/System.IO.File.WriteAllBytes/p/…
-
dave317 over 7 yearsI'm actually not using xamarin at all. I think thats my issue. I'm using ASP.NET. I have a using System.IO; statement in my controller, but its not working.
-
Mario Galván over 7 years@dave317 that may be the problem.
-
Jesper over 4 yearsYou should remove that regex matching as it is very slow. You could use something like this instead:
s.Substring(s.IndexOf(",")+1).Trim();
-
-
321X over 3 yearsNo need for the regex. You only need to split at the comma to get the data from the data url. Official format is:
data:[<mediatype>][;base64],<data>