Convert from a DataUrl to an Image in C# and write a file with the bytes

18,037

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:

enter image description here

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;
}
Share:
18,037

Related videos on Youtube

Mario Galván
Author by

Mario Galván

I am Mexican Mobile developer and Xamarin enthusiast! follow me on twitter: @MayitoGalvan

Updated on June 15, 2022

Comments

  • Mario Galván
    Mario Galván almost 2 years

    Hello I have signature like this:

    enter image description here

    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
      SLaks over 9 years
      What error do you get?
    • SLaks
      SLaks over 9 years
      Why are you creating a MemoryStream?
    • Jason
      Jason over 9 years
      Is 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
      Mario Galván over 9 years
      Looking 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
      Jason over 9 years
      what are the values of path and filename? It sounds like you are not building a valid path.
    • Mario Galván
      Mario Galván over 9 years
      You 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
      Fran_gg7 over 8 years
      Hi 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
      Mario Galván over 8 years
      To 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
      dave317 over 7 years
      How did you make this work in C#? WHen I try and use File.WriteAllBytes, it is looking for 3 string arguments....
    • Mario Galván
      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.WriteAllByte‌​s/p/…
    • dave317
      dave317 over 7 years
      I'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
      Mario Galván over 7 years
      @dave317 that may be the problem.
    • Jesper
      Jesper over 4 years
      You should remove that regex matching as it is very slow. You could use something like this instead: s.Substring(s.IndexOf(",")+1).Trim();
  • 321X
    321X over 3 years
    No 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>