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;
}
Related
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
I am trying to allow users to upload a new profile pic by clicking on the old one.
I am using ajax and a file reader to do so
$('#profileImage').click(function(){ $('#image-file').trigger('click'); });
$('#image-file').on('change',function(){
if (this.files && this.files[0]) {
var FR= new FileReader();
FR.readAsDataURL(this.files[0]);
FR.addEventListener("load", function(e) {
document.getElementById("profileImage").src = e.target.result;
imgData = e.target.result;
var formData = {
'name' : localStorage.getItem('email'),
'image' : imgData
};
console.log("image data: " + imgData);
$.ajax({
type : 'POST',
url : '/uploadprofile.php',
data : formData,
dataType: 'text',
encode : true
}).done(function(data) {
console.log(data);
});
});
}
});
The new image is loaded onto the old picture and the console tracks the image data sent through.
The only issue is that the newly updated picture is not visible to the container. It shows an icon of a broken picture.
This is my php file that handles the insertion
$json = json_decode(file_get_contents('php://input'),true);
if ($json == "") {
$name = $_POST['name'];
$image = $_POST['image'];
} else {
$name = $json["name"]; //within square bracket should be same as Utils.imageName & Utils.image
$image = $json["image"];
}
$response = array();
$decodedImage = base64_decode("$image");
//unlink old picture
// unlink($name.".jpg");
$oldName = $name;
$name .= date("D M d Y G:i");
$name = str_replace(' ', '', $name);
$fullPath = "http://www.mywebsite.com/uploads/".$name.".jpg";
$return = file_put_contents("uploads/".$name.".jpg", $decodedImage);
if($return !== false){
$response['email'] = $oldName;
$response['image'] = $image;
$response['success'] = 1;
$response['message'] = "Image Uploaded Successfully";
$sql = "UPDATE Users SET PicLocation = '$fullPath' WHERE Email = '$oldName'";
$result = $conn->query($sql);
}else{
$response['success'] = 0;
$response['message'] = "Image Uploaded Failed";
}
echo json_encode($response);
The value for $response['image'] that gets printed out is correct but it doesn't seem to show the picture. The data is corrupted somehow. Is there something I should do to get the correct data?
Additionally, sometimes I get the error:
jquery.min.js:2 POST http://tanglecollege.com/uploadprofile.php 406 (Not Acceptable)
I don't know what it means and there doesn't seem to be a good explanation.
Also, the file that gets saved to the server is corrupted in some way. I can track the base64 data being passed along from js to php but when it is saved as a file, that file is corrupted and the image can not be read from the filepath.
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.';
?>
What I am trying to do:
Essentially I am trying to upload a file to a directory on the server that a user uploads via a HTML <input type="file"> element.
To do this I am creating a new XMLHttpRequest on the <input> element's change event which should send the data of the uploaded file to the upload.php file which would then handle the uploaded file and upload it to the server asynchronously.
My Code:
HTML
<form class="js-upload-form" method="POST" action="upload.php" enctype="multipart/form-data">
<input class="button js-uploaded-file" type="file" name="file" />
</form>
JS
document.querySelector('.js-uploaded-file').addEventListener('change', function() {
let file = this.files[0];
let formData = new FormData();
formData.append('file', file);
let xhr = new XMLHttpRequest();
xhr.open('POST', 'upload.php', true);
xhr.setRequestHeader('Content-type', 'multipart/form-data');
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
let percentComplete = (e.loaded / e.total) * 100;
console.log(percentComplete + '% uploaded');
}
};
xhr.onload = function() {
if (this.status == 200) {
console.info(this.response);
}
};
xhr.send(formData);
}, false);
PHP (upload.php)
print_r($_FILES);
$currentDir = getcwd();
$uploadDirectory = "/uploads/";
$errors = []; // Store all foreseen and unforseen errors here
$fileName = preg_replace("/[^A-Z0-9._-]/i", "_", $_FILES['file']['name']);
$fileSize = $_FILES['file']['size'];
$fileTmpName = $_FILES['file']['tmp_name'];
$fileType = $_FILES['file']['type'];
$uploadPath = $currentDir . $uploadDirectory . $fileName;
if ($fileSize > 2000000) {
$errors[] = "This file is more than 2MB. Sorry, it has to be less than or equal to 2MB";
}
if (empty($errors)) {
$didUpload = move_uploaded_file($fileTmpName, $uploadPath);
if ($didUpload) {
echo "The file " . basename($fileName) . " has been uploaded";
} else {
echo "An error occurred somewhere. Try again or contact the admin";
}
} else {
foreach ($errors as $error) {
echo $error . "These are the errors" . "\n";
}
}
My Problem
This code is simply not working. Printing the $_FILES array returns an empty array, and console logging the xhr.response logs the error message set in the PHP ('An error occurred somewhere. Try again or contact the admin'). I would really appreciate any help on solving this issue as I have looked through countless other online resources regarding this issue and even though I feel like my code does exactly what they all say to do, it still doesn't work.
What I've tried:
I tried simply submitting the form instead of trying to do so using the FormData() object and <input> change event by adding a submit button and although the page redirected to ...url/upload.php and didn't work asynchronously, the $_FILES array contained the correct data of the uploaded file and the file was uploaded to the server, which makes me think there must be an issue in my Javascript code, either relating to the XMLHttpRequest or the FormData object.
Normally, XMLHttpRequest will generate an appropriate Content-Type from the FormData object.
You, however, are overriding it with one you created manually:
xhr.setRequestHeader('Content-type', 'multipart/form-data');
However, the mandatory boundary attribute is missing, so PHP can't find the points to split the parts of the request up.
Don't override the Content-Type. Remove the quoted line.
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);
});