HTML
HTML5: Saving Canvas Image Data Using PHP And Ajax
October 30, 2010
0

In this tutorial, we will demonstrate methods of saving the content of a HTML5 Canvas object using server side scripting. PHP will be used in this example, but the technique can be applied in other languages as well.

This post requires understanding of Javascript, HTML (especially forms and/or AJAX). PHP is used in the example but the code is fairly simple and can be replicated in other languages.

Here’s The Example

Client Side

To retrieve the image data, use toDataURL(type, quality) method on a Canvas object.

  • the typeparameter is the image format to use: image/png, image/jpeg, etc. Current W3 standard (http://www.w3.org/TR/html5/the-canvas-element.html#dom-canvas-todataurl) says that only PNG is required for browsers to conform to HTML 5 spec, so for this example, I’ll only be using PNG.
  • the quality parameter is a number between 0.0 to 1.0 to specify the quality of the image encoding, higher number means better quality. If unspecified, the default value will be used. Note: I am having issues when specifying a second parameters in Firefox 3.6, so I’ll leave this parameter unspecified (update: looks like the second parameter is valid if you specify image/jpg, but not valid on image/png).

Here’s an example of the code that receives the canvas data.

var canvasData = testCanvas.toDataURL("image/png");

The content of the canvasData will look like this (shortened and newlines added for aesthetic):

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAGB
ElEQVR4nO3UMVEEABAEwZNFBiGOeAe8I0LIsIWCDUinuqtOwAZzd3cvd/fhnMvf6wU87u737
p7Ouez93N3nBTwgCnTeWYIMGU6zwwBpkznmSHAlOk8MwSYMp1nhgBTpvPMEGDKdJ4ZAk
yZzjNDgCnTeWYIMGU6zwwBpkznmSHAlOk8MwSYMp1nhgBTpvPMEGDKdJ4ZAkyZzjNDgCn
e10Ue1tvdPZ1z+Xs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAIB/+gMqleRG3CrxcAAAAABJRU5ErkJggg==

The real image data comes after the “,” (comma) sign — meaning everything after the data:,. The data is base64 encoded so you can send it as part a POST variables safely as text (GET is generally not recommended since it has length limitation and images can easily gets large).

In the HTML side, let’s use AJAX to send the data:

var canvasData = testCanvas.toDataURL("image/png");
var ajax = new XMLHttpRequest();
ajax.open("POST",'testSave.php',false);
ajax.setRequestHeader('Content-Type', 'application/upload');
ajax.send(canvasData );

The code above sends out the canvasData as a raw POST variable. One thing to pay attention here is the
Content-Type should NOT be set to application/x-www-form-urlencoded but something unknown because basically we want the browser to send the data in its raw state.

This raw data will be available in php variable $GLOBALS[“HTTP_RAW_POST_DATA”]. This code calls a .php script named testSave.php — this script is explained below.

PS: If you need to pass parameters to the back end, you can set Content-Type is set to application/x-www-form-urlencoded, but there’s a caveat where you must handle the URL decoding (basically you need to revert “spaces” into “+”).  See this tutorial for details:
/2016/07/html5-saving-canvas-image-data-and-passing-parameters-using-html-form-and-php

 

ServerSide

Here’s testSave.php, a basic script that retrieves the raw POST data from the client and saves the data into a file.

<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
  // Get the data
  $imageData=$GLOBALS['HTTP_RAW_POST_DATA'];

  // Remove the headers (data:,) part.
  // A real application should use them according to needs such as to check image type
  $filteredData=substr($imageData, strpos($imageData, ",")+1);

  // Need to decode before saving since the data we received is already base64 encoded
  $unencodedData=base64_decode($filteredData);

  //echo "unencodedData".$unencodedData;

  // Save file. This example uses a hard coded filename for testing,
  // but a real application can specify filename in POST variable
  $fp = fopen( 'test.png', 'wb' );
  fwrite( $fp, $unencodedData);
  fclose( $fp );
}
?>

Notes

  • We are assuming that the file is always a PNG although you can easily check for file type by examining the portion before the comma.
  • The data is base64 encoded so we need to decode it (in PHP, you can just use base64_decode() function to do that, other languages should have similar function since this is a common operation). Then it’s just a matter of saving the decoded data into a file.
  • In this example, to simplify the code, the data is always saved to a file named test.png.
  • A common debugging issue is the file is not written because the script does not have the permission to write file. If you’re encountering issue, check that first, perhaps by writing a basic script to write a dummy file.
  • Note: In Internet Explorer 9 (Beta), you must have this line somehwhere before the html content (weird!):
    <!DOCTYPE html>
    

Here’s a bare-bone test page: https://www.permadi.com/tutorial//tutorial/save-canvas/test-save-html5-canvas.html

The example were tested on Firefox 3.6 (Windows), Chrome 7.0.517.41 (Windows), Internet Explorer 9 (Windows), Safari 4.04.4 (Mac), Chrome 7.0.517.41 (Mac).

Here is another example that automatically downloads the saved file via the browser Downloader:
https://www.permadi.com/tutorial/save-canvas/test-download-html5-canvas.html