/    Sign up×
Community /Pin to ProfileBookmark

Saving canvas “images” from a mobile device

Heya fellow devs!

I’ve been trying to make a digital signature pad for the past few weeks, but have been running into the issue of saving canvas “images” to the server from a touch interface. Despite the image data sending perfectly fine when testing from Visual Studio and from the live website on a regular Windows PC, the iPad seems incapable of sending the Base64 code through the static JavaScript function I’ve set in the ASP files. However, rather than give me a standard error screen, submitting a signature from the iPad creates an empty .png file — the likes of which Windows 10 cannot open because “it looks like we don’t support this file format.” To add to this, I’m given a blank document when opening the file in Notepad.

The code I’ve written to create an image from a signature can be seen below. Please note the “_function DrawPad() {…}_” — which was made following these links:

  • https://www.html5canvastutorials.com…t-application/

  • https://jsfiddle.net/gfcarv/66nVn/

  • https://jsfiddle.net/sdncP/
  • “`
    <body data-rsssl=”1″ onload=”DrawPad()”>
    <form id=”form1″ runat=”server”>
    <asp:ScriptManager ID=”ScriptManager1″ runat=”server”></asp:ScriptManager>
    <input type=”hidden” id=”imageData” runat=”server” class=”image-data” />
    <canvas id=”myCanvas” width=”500″ height=”100″></canvas>
    <br />
    <asp:Button ID=”btnSave” runat=”server” Text=”Submit” />
    </form>
    <script type=”text/javascript” id=”jsDraw”>
    var canvas = document.getElementById(‘myCanvas’);
    var ctx = canvas.getContext(‘2d’);
    function DrawPad() {…} // see the bullet points for this one

    $(“#btnSave”).click(function () {
    var image = document.getElementById(‘myCanvas’).toDataURL(“image/png”);
    image = image.replace(‘data:image/png;base64,’, ”);
    $.ajax({
    type: ‘POST’,
    url: ‘Default.aspx/UploadImage’,
    data: ‘{ imageData : “‘ + image + ‘” }’,
    contentType: ‘application/json; charset=utf-8’,
    dataType: ‘json’
    });
    });
    </script>
    </body>
    “`

    At the risk of getting slapped on the wrist for posting C# code on a JS board (new guy — sorry!), here is what happens on the ASP side when btnSave is pressed:

    “`
    public static void UploadImage(string imageData)
    {
    using (FileStream fs = new FileStream(@”C:\Users\Alex\Documents\testpic.png”, FileMode.Create))
    {
    using (BinaryWriter bw = new BinaryWriter(fs))
    {
    bw.Write(Convert.FromBase64String(imageData));
    bw.Close();
    }
    }
    }
    “`

    I’ve asked others whether this issue is related to the FileStream or BinaryWriter or something within the JavaScript side of this app, but so far the most I have gotten back is a comment about how I should utilize the iOS “Files” app and directory when (and I should stress this clearly) the work I’m doing here is NOT for a mobile app, but for a website that users will access from a mobile device. And I would like to stress one more time: this web app works perfectly fine on a desktop environment with a modern browser, but not on any mobile device I’ve tested on — and I cannot wrap my head around why this is.

    to post a comment
    JavaScript

    3 Comments(s)

    Copy linkTweet thisAlerts:
    @SempervivumAug 07.2019 — When viewing your code I was confused about:
  • 1. `contentType: 'application/json; charset=utf-8',</C> as the manual of jQuery.ajax says: <QUOTE>contentType (default: 'application/x-www-form-urlencoded; charset=UTF-8')<br/>
    Type: Boolean or String<br/>
    When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases.[/quote]</QUOTE></LI>
    <LI>2. <C>
    data: '{ imageData : "' + image + '" }',`
    - AFAIK if this parameter is a string it has to be a query string. Or the parameter has to be a plain object.


  • Inserting your code into a test file (minor modifications in order to adjust it to my PHP test configuration) these concerns proved true: I had to change the contentType to the one recommend by the manual and the parameter data to a plain object.

    This code works fine me:
    &lt;script type="text/javascript" id="jsDraw"&gt;
    var canvas = document.getElementById('myCanvas');
    var ctx = canvas.getContext('2d');
    // function DrawPad() {... } // see the bullet points for this one
    ctx.fillStyle = 'blue';
    ctx.fillRect(10, 10, 50, 50);
    $("#btnSave").click(function () {
    var image = document.getElementById('myCanvas').toDataURL("image/png");
    image = image.replace('data:image/png;base64,', '');
    $.ajax({
    type: 'POST',
    url: 'savepic.php',
    data: { imageData: image },
    // data: '{ imageData : "' + image + '" }',
    contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
    // dataType: 'json',
    success: function (output) {
    console.log(output);
    }
    });
    });
    &lt;/script&gt;
    However I'm not completely shure if this will be suitable for your ASP configuration and will fix your issue.
    Copy linkTweet thisAlerts:
    @AlReyauthorAug 08.2019 — @Sempervivum#1607314 that's interesting -- but unfortunately, that did not work for my solution. If I change a single one of those lines to what you have here, the file won't even show up in the directory I established. I've seen some people use the _{ imageData: image}_ solution before, but I've heard others say that you don't want to use it when you're trying to get an image from the canvas -- and from what I can tell, that method of obtaining the image doesn't work. This could possibly be because I'm not using any PHP in my solution, though, since I'm working in Visual Studio and implementing PHP in the system would take up more time than my company's willing to put forward.
    Copy linkTweet thisAlerts:
    @AlReyauthorAug 12.2019 — It turns out the problem is moreso a C# issue than a JavaScript issue -- specifically in the way the C# code was taking the Base64 code and writing it to a file. With that said, everything in the first block of code I put was correct; the issue was in UploadImage, which has been fixed as such:
    ``<i>
    </i>public static void UploadImage(string imageData)
    {
    var impersonator = new ImpersonationHelper("&lt;domain&gt;", "&lt;username&gt;", "&lt;password&gt;");
    impersonator.StartImpersonating();
    string path = @"\\PATH\TO\FILE\DIRECTORY\";
    if (!Directory.Exists(path)) // creates a new folder if this one doesn't currently exist yet
    Directory.CreateDirectory(path);
    string fileNameWithPath = path + "SIG" + DateTime.Now.ToString("MMddyyyy") + "-" + rand + ".png"; // where rand is randomly-generated elsewhere
    byte[] imageBytes = Convert.FromBase64String(imageData);
    File.WriteAllBytes(fileNameWithPath, imageBytes);
    impersonator.StopImpersonating();
    }<i>
    </i>
    ``
    ×

    Success!

    Help @AlRey spread the word by sharing this article on Twitter...

    Tweet This
    Sign in
    Forgot password?
    Sign in with TwitchSign in with GithubCreate Account
    about: ({
    version: 0.1.9 BETA 3.29,
    whats_new: community page,
    up_next: more Davinci•003 tasks,
    coming_soon: events calendar,
    social: @webDeveloperHQ
    });

    legal: ({
    terms: of use,
    privacy: policy
    });
    changelog: (
    version: 0.1.9,
    notes: added community page

    version: 0.1.8,
    notes: added Davinci•003

    version: 0.1.7,
    notes: upvote answers to bounties

    version: 0.1.6,
    notes: article editor refresh
    )...
    recent_tips: (
    tipper: @darkwebsites540,
    tipped: article
    amount: 10 SATS,

    tipper: @Samric24,
    tipped: article
    amount: 1000 SATS,

    tipper: Anonymous,
    tipped: article
    amount: 10 SATS,
    )...