How to save canvas image to server with JavaScript and PHP?

Tags: ,



I’m struggling with saving my canvas image to server using JavaScript and PHP. I’ve tried multiple examples for both JS and PHP and it always fails. There’s conflicting advice on how to send image data to PHP script (base64, blob, FormData) and I’m not sure how best to communicate back to JS. Currently, zero bytes PNG files are being saved to server and I’m not sure why. I’d like to save generated canvas as a PNG on server and execute a command in JS on success. How best to approach it?

JS:

var off_canvas = document.createElement('canvas');
off_canvas.width = 1080;
off_canvas.height= 1080;
var ctx = off_canvas.getContext("2d");
var brick = new Image();
brick.src = '../img/brick-white.jpg'; 
brick.onload = function(){
    var pattern = ctx.createPattern(this, "repeat");
    ctx.fillStyle = pattern;
    ctx.fill();
};
var base64img = off_canvas.toDataURL("image/jpeg");

fetch("../php/save_image.php", {
    method: "POST",
    image: base64img
})  .then(response => response.text())
    .then(success => console.log(success)) //execute command
    .catch(error => console.log(error));

PHP:

<?php
    $img = $_POST['image'];
    $img = str_replace('data:image/png;base64,', '', $img);
    $img = str_replace(' ', '+', $img);
    $data = base64_decode($img);
    
    if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/img")) {
        mkdir($_SERVER['DOCUMENT_ROOT'] . "/img", 0777, true);
    }
    
    $file = $_SERVER['DOCUMENT_ROOT'] . "/img/".time().'.png';
    
    $success = file_put_contents($file, $data);
    print $success ? $file.' saved.' : 'Unable to save the file.';
?>

Answer

After some fiddling with multiple options on both JS and PHP, this is what finally worked:

JS

var off_canvas = document.createElement('canvas');
off_canvas.width = 1080;
off_canvas.height = 1080;
var off_ctx = off_canvas.getContext("2d");

off_ctx.beginPath();
off_ctx.rect(20, 20, 150, 800);
off_ctx.fillStyle = "red";
off_ctx.fill();

var brick = new Image();
brick.src =  "img/brick-white.jpg";
brick.onload = function(){
    var pattern = off_ctx.createPattern(brick, "repeat");
    off_ctx.fillStyle = pattern;
    off_ctx.fillRect(500, 0, 1000, 1000);
    
    // needs delay to fully render to canvas
    var timer = window.setTimeout(save_canvas(off_canvas), 500);
};

function save_canvas(c) {
    var b64Image = c.toDataURL("image/png");
    
    fetch("../php/save_image_b64.php", {
        method: "POST",
        mode: "no-cors",
        headers: {"Content-Type": "application/x-www-form-urlencoded"},
        body: b64Image
    })  .then(response => response.text())
        .then(success => console.log(success))
        .catch(error => console.log(error));
}

PHP

<?php
    $img = file_get_contents("php://input"); // $_POST didn't work
    $img = str_replace('data:image/png;base64,', '', $img);
    $img = str_replace(' ', '+', $img);
    $data = base64_decode($img);
    
    if (!file_exists($_SERVER['DOCUMENT_ROOT'] . "/img")) {
        mkdir($_SERVER['DOCUMENT_ROOT'] . "/img", 0777, true);
    }
    
    $file = $_SERVER['DOCUMENT_ROOT'] . "/img/".time().'.png';
    
    $success = file_put_contents($file, $data);
    print $success ? $file.' saved.' : 'Unable to save the file.';
?>


Source: stackoverflow