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.';
?>
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.';
?>
in your js page add console.log(base64img);
in your browser console, copy object. i use firefox, if you use something else, then from there copy console message.
the message will be data:image/jpeg;base64,/9j/4AAQSk......
in your php page;
$img = "data:image/jpeg;base64,/9j/4AAQSk.....";
echo "<img src='$data' />"; exit;
now you will know the image is coming or not.
if image is not showing you are not implementing the fetch method correctly
if image is showing, see if you are able to create dir/file. that is, apache has permission to create dir/file. if you are able
Related
I'm converting svg using html2canvas to save on server side as png product preview before checkout with base64. The svg works fine. It's for a customized item checkout. The problem is after customization and checkout is clicked, the svg image does not save to preview on checkout page before checking out. Reason is i don't what to write to for the php to save it. I need help in writing the php code for "savetoserver.php" to save to server
function imagetopng(){
function showCheckout() {
$("#checkoutcontainer").show();
$(".productoverview").show();
$("#popup").show();
}
setTimeout(showCheckout, 500);
html2canvas($(".stole"), {
allowTaint: true,
letterRendering: true,
onrendered: function(canvas) {
$('.stole-png').prepend(canvas);
var dataURL = canvas.toDataURL('image/png', 1.0);
$.ajax({
type: "POST",
url: "savetoserver.php",
data: {
imgBase64: dataURL
}
})
.done(function(o) {
var fileurl = o;
var websiteurl = "http://woven.indexsta.com/";
var formatted = websiteurl + fileurl;
//var formatted = "stole-designs/" + fileurl
$('#stole-url').attr('value', formatted);
$('#stolepreview').attr('src', fileurl);
// If you want the file to be visible in the browser
// - please modify the callback in javascript. All you
// need is to return the url to the file, you just saved
// and than put the image in your browser.
});
}
});
$('.stole-png').empty();
};
$('#closecheckout').on('click touch',function(){
$("#checkoutcontainer").css('display','none');
$("#popup").css('display','none');
});
I figured it out. Incase anyone faces same challenge, here's the script i wrote to solve it.
<?php
// requires php5+
// create directory
if (!file_exists('images/')) {
mkdir('images/', 0777, true);
}
define('UPLOAD_DIR', 'images/');
$img = $_POST['imgBase64'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>
I have a page with a canvas. I'm using signaturPad to capture a signature. I now need to send this signature to the php page to process and save
var saveButton = document.getElementById('save');
var cancelButton = document.getElementById('clear');
saveButton.addEventListener('click', function (event) {
var canvas = document.getElementById('signature-pad');
var dataURL = canvas.toDataURL();
console.log(dataURL);
$.ajax({
type: "POST",
url: "user_group_start_paperwork_esign2.php?group_id=1389",
data: dataURL,
//dataType: "html",
cache: false,
success: function(data){//console.log(data)
}
});
And on the PHP side
define('UPLOAD_DIR', 'images/');
$img = $_POST['data'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
But I don't seem to be sending anything. The console.log is getting the data but the $_POST['data'] seems to be empty. Thanks
I have a page that I use to have users press a submit button to insert MYSQL data but also capture an image and upload a .png file to a directory all from the click of one submit button. 9/10 this works perfectly. I'm not sure if it's a connectivity issue (it's being done on a wireless device) or if it's my code. That 1/10 times it will INSERT the MYSQL data but it will not upload the image to the server. Below is my upload code from my file and the upload_data.php file that the code calls. Sorry my formatting on this site isn't the greatest.
<script>
function uploadEx() {
var canvas = document.getElementById("canvasSignature");
var dataURL = canvas.toDataURL("image/png");
document.getElementById('hidden_data').value = dataURL;
var fd = new FormData(document.forms["form"]);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/inc/img/inspection/upload_data.php', true);
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
var percentComplete = (e.loaded / e.total) * 100;
console.log(percentComplete + '% uploaded');
//alert('Succesfully uploaded');
}
};
xhr.onload = function() {
};
xhr.send(fd);
};
</script>
BELOW IS UPLOAD_DATA.PHP
<?php
$upload_dir = "upload/";
$img = $_POST['hidden_data'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$id = $_POST['sub_id'];
$file = $upload_dir . $id . ".png";
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>
Based on your comment, you are not cancelling the default submit event and that would cause the form to be submitted. And that could cause the ajax request to not finish always.
If you use inline javascript like you do (I would try to move all inline js to the script itself...), you need to make sure that you use something like:
onsubmit="return uploadEx();"
and
onclick="return uploadEx();"
And in your uploadEx() function you end with:
function uploadEx() {
// your code
return false;
}
i have this code, either the ajax isn't transferring the data correctly or my php doesn't work properly. i know the canvass is saving to data png it writes to the page. Is there a way to just convert it to a file and save it from javascript?
START JAVASCRIPT:-------------------
<-- get the canvass element and convert to data png -->
var canvas = document.getElementById("textCanvas");
var img = canvas.toDataURL("image/png");
<-- END the canvass element and convert to data png -->
<-- SEND to php file -->
var onmg = encodeURIComponent(img);
var xhr = new XMLHttpRequest();
var body = "img=" + onmg;
xhr.open('POST', "convertit.php",true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.setRequestHeader("Content-Length", body.length);
xhr.setRequestHeader("Connection", "close");
xhr.send(body);
xhr.onreadystatechange = function () {
if (xhr.status == 200 && xhr.readyState == 4) {
document.getElementById("div").innerHTML = xhr.responseText;
} else {
document.getElementById("div").innerHTML = 'loading';
}
}
<-- END send to php file -->
END JAVASCRIPT:-------------------
START PHP:-------------------
$img = $_POST['img'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
file_put_contents('/uploads/file.png', $data);
END PHP:-------------------
changed the php to -------->
define('UPLOAD_DIR', 'images/');
$img = $_POST['img'];
$img = str_replace('data:image/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . 'txtimg.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
which i got from ----->http://j-query.blogspot.com/2011/02/save-base64-encoded-canvas-image-to-png.html
-cheers works awesome :)
I am trying to get a canvas that I have saved to pop up in my html window. Not sure how to grab it on the html page because the save generates a random name for the image.
The Save code:
function saveImage() {
cursor.visible = false; stage.update();
var canvasData = testCanvas.toDataURL("image/png");
window.open(("../popup.html"));
var xmlHttpReq = false;
if (window.XMLHttpRequest) {
ajax = new XMLHttpRequest();
cursor.visible = true; stage.update();
}
else if (window.ActiveXObject) {
ajax = new ActiveXObject("Microsoft.XMLHTTP");
}
alert (nameOfFile);
ajax.open('POST', 'testSave.php', false);
ajax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajax.onreadystatechange = function() {
console.log(ajax.responseText);
}
ajax.send("imgData="+canvasData);
}
The PHP:
<?php
// requires php5
define('UPLOAD_DIR', 'images/');
$img = $_POST['img'];
$img = str_replace('data:images/png;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.png';
$success = file_put_contents($file, $data);
print $success ? $file : 'Unable to save the file.';
?>
The popup.html
<div><strong>Image to display below</strong></div>
<script>
window.onload = function() {
document.getElementById('imgData="+canvasData').src = localStorage.getItem('images/');
};
</script>
Your PHP is already returning the $file that was created on the server.
So, you could POST with jQuery and add a callback that receives that unique filename created on the server (or the error message if an error occurred).
// create a dataUrl from the canvas
var dataURL= canvas.toDataURL();
// post the dataUrl to php
$.ajax({
type: "POST",
url: "upload.php",
data: {image: dataURL}
}).done(function( respond ) {
// you will get back the temp file name
// or "Unable to save this image."
console.log(respond);
});