Sending Images from Canvas Elements Using Ajax and PHP $_Files

Sending images from Canvas elements using Ajax and PHP $_FILES

Building on Nathan's excellent answer, I was able to finnagle it so that it is still going through jQuery.ajax. Just add this to the ajax request:

            xhr: function () {
var myXHR = new XMLHttpRequest();
if (myXHR.sendAsBinary == undefined) {
myXHR.legacySend = myXHR.send;
myXHR.sendAsBinary = function (string) {
var bytes = Array.prototype.map.call(string, function (c) {
return c.charCodeAt(0) & 0xff;
});
this.legacySend(new Uint8Array(bytes).buffer);
};
}
myXHR.send = myXHR.sendAsBinary;
return myXHR;
},

Basically, you just return back an xhr object that is overriden so that "send" means "sendAsBinary". Then jQuery does the right thing.

Convert and upload canvas as image

The Access-Control-Allow-Origin header error means your service doesn't allow cross-domain requests.

You can change this header like so (php):

 header("Access-Control-Allow-Origin: *");

Note that this will allow requests from any domain, for security reasons I would recommend replacing the * with the domain name you want to make requests from.

Save Uploaded image in canvas to server

The main issue is that some server-side language is necessary here... sure, you can (ajax) POST the base64 but something on the server has to know what to do with the POST(ed) data it receives.

Below is the PHP (server side code) I used on a previous project to allow the user to upload their own avatar image.

In my use case I have the ajax POST sending 3 things:

  1. the users image file name
  2. the users image file extension (png, jpg or gif)
  3. the raw base64 encoding data

The PHP should be fairly self explanatory, but let me know if you have any questions.

You MAY need to make sure that the permissions on the folder where you're writing the image will in fact allow the PHP process to write. Sometimes I've had to tweak folder permissions, just depends on the host platform configuration.

If it doesn't work, you can set PHP Errors to ON so it'll respond with details about what problems PHP is having. (a quick google search should help with that).

You can simplify my example code with a single known file type and file name to do a quick test. If you need help with it I might be able to connect with you via email to get details and assist. (I remember how eager I was to get this working when I dealt with it -- I feel your pain!!!).

Updated PHP source code for the working solution:

if( isset($_POST['imgBase64']) && isset($_POST['imgFileName']) && 
isset($_POST['imgFileType']) ){

$fname = filter_input(INPUT_POST, 'imgFileName'); // THE FILENAME THE USER CHOSE IS RECEIVED VIA POST
$img = filter_input(INPUT_POST, 'imgBase64'); // THE BASE64 ENCODING RECEIVED VIA POST
$imgtype = filter_input(INPUT_POST, 'imgFileType'); // THE FILE TYPE / EXTENSION IS RECEIVED VIA POST

// STRIP OFF THE BEGINNING OF THE BASE64 DATA, BUT DEPENDS ON THE IMAGE TYPE.
// I COULD HAVE SIMPLIFIED THIS BUT USED IF STATEMENTS.
if ( $imgtype === 'png'){
$img = str_replace('data:image/png;base64,', '', $img);
};
if ( $imgtype === 'jpg' || $imgtype === 'jpeg'){
$img = str_replace('data:image/jpeg;base64,', '', $img);
};
if ( $imgtype === 'gif'){
$img = str_replace('data:image/gif;base64,', '', $img);
};

// REPLACE ALL SPACES IN THE IMAGE DATA WITH PLUS SYMBOL
$img = str_replace(' ', '+', $img);
// CONVERT THE DATA FROM BASE64 ENCODING
$img = base64_decode($img);

// SAVE THE FILE
file_put_contents('...path.../'.$fname, $img);

echo '{"error":false, "message":"Image has been saved successfully!","data":[{"fileName": "'.$fname.'"}]}';
}

Uploading 'canvas' image data to the server

You don't need a file input, just get the data with ctx.getImageData() and post it to the server with Ajax.

See the MDN Documentation for CanvasRenderingContext2D.getImageData().

But you won't be able to get the image data in IE, even with ExCanvas.

How to save an HTML5 Canvas as an image on a server?

Here is an example of how to achieve what you need:

  1. Draw something (taken from canvas tutorial)

<canvas id="myCanvas" width="578" height="200"></canvas>

<script>
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');

// begin custom shape
context.beginPath();
context.moveTo(170, 80);
context.bezierCurveTo(130, 100, 130, 150, 230, 150);
context.bezierCurveTo(250, 180, 320, 180, 340, 150);
context.bezierCurveTo(420, 150, 420, 120, 390, 100);
context.bezierCurveTo(430, 40, 370, 30, 340, 50);
context.bezierCurveTo(320, 5, 250, 20, 250, 50);
context.bezierCurveTo(200, 5, 150, 20, 170, 80);

// complete custom shape
context.closePath();
context.lineWidth = 5;
context.fillStyle = '#8ED6FF';
context.fill();
context.strokeStyle = 'blue';
context.stroke();
</script>


Related Topics



Leave a reply



Submit