Upload, resize and send images to server with javascript - javascript

After struggling with this issue for 2 days, reading a lot of material online, here I am begging for your help.
I'm trying to resize some images uploaded via FileReader, resize with canvas and send to my server with php.
Everything works as expected, except when I try to upload multiple files.
The script loads only the last image, despite showing base64 data for all images with a console.log ();
I'm missing something that I don't know what it is.
Here is the code:
<input type="file" id="input" onchange="process()" multiple/>
function process(){
const file = document.querySelector("input").files;
var abc = [];
for(i = 0; i<file.length; i++){
if(!file[i]) return;
const reader = new FileReader();
reader.readAsDataURL(file[i]);
reader.onload = function(event){
const imgElement = document.createElement("img");
imgElement.src = event.target.result;
imgElement.onload = function(e){
const canvas = document.createElement("canvas");
const MAX_WIDTH = 800;
const scaleSize = MAX_WIDTH / e.target.width;
canvas.width = MAX_WIDTH;
canvas.height = e.target.height * scaleSize
const ctx = canvas.getContext("2d");
ctx.drawImage(e.target, 0,0, canvas.width, canvas.height)
var srcEncoded = ctx.canvas.toDataURL(e.target, "image/jpeg");
sendToServer(srcEncoded);
}
};
}
}
function sendToServer(data){
let formData = new FormData();
formData.append("foto", data);
fetch('teste.php', {method: "POST", body: formData});
}
As gugateider said, the javascript part its ok.
I think the problem its on the server side.
It only saves the last image no mather how much I selecte in the input.
Unfortunately I only have a PHP server, which is enough, but it limits the possibilities of solutions for this technology.
Here is the php code.
$data = $_POST['foto'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents(round(microtime(true)).'_image.png', $data);

Problem Solved!
I think the round(microtime(true)) wasn't enough to generate unique names.
I changed it to uniqid() and worked.
So the PHP code becomes:
$data = $_POST['foto'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents(uniqid().'_image.png', $data);

Related

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

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

Uploading Picture Is Corrupted

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.

Image corrupted when using Cropit and form submit

I was introduced to Cropit recently and find it really easy to use but I am stuck at one area. I am trying to use Cropit and form submit. I am following the demo provided by Cropit.
Javascript:
$('form').submit(function() {
// Move cropped image data to hidden input
var imageData = $('.image-editor').cropit('export');
$('.hidden-image-data').val(imageData);
// Print HTTP request params
var formValue = $(this).serialize();
$('#result-data').text(formValue);
// Prevent the form from actually submitting
return false;
});
PHP:
$encoded = $base64_string;
$decoded = urldecode($encoded);
$image_name = explode(';', $decoded);
$image_name = explode(':', $image_name[0]);
$image = array_pop($image_name);
$ext = explode('/', $image);
//decode the url, because we want to use decoded characters to use explode
$decoded = urldecode($encoded);
//explode at ',' - the last part should be the encoded image now
$exp = explode(',', $decoded);
//we just get the last element with array_pop
$base64 = array_pop($exp);
//decode the image and finally save it
$data = base64_decode($base64);
$str = random_string('alnum', 8);
$file = $str.'.'.$ext[1];
$data = $upload;
file_put_contents('assets/image_test/cropped/'.$file, $data);
It is able to output the file into my folder but the picture is just a blank screen with the dimension I set.
I have try to search the web but I couldn't find any solution to my problem.
Hope to get help from anyone who have encounter or know a solution.

File doesn't always upload to server using PHP & Javascript

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;
}

fengyuanchen jQuery cropper plugin - how to get cropped canvas

How to get crop the image using my own button?
I tried to execute this
var canvas = $selector.cropper('getCroppedCanvas')
but it's returning null value.
Is there a way to get the cropped canvas? And how can I put the cropped canvas data into <input type="file"> value and send it to PHP?
Your selector should be the HTML container which contains the image:
The Javascript and HTML should be like as mentioned below:
$img = $('#uploader-preview');
$img.cropper('getCroppedCanvas');
var canvaURL = canvas.toDataURL('image/jpeg'); // it returns the cropped image / canvas
<img src="" id="uploader-preview">
Send Canvas Image to PHP:
var photo = canvas.toDataURL('image/jpeg');
$.ajax({
method: 'POST',
url: 'photo_upload.php',
data: {
photo: photo
}
});
Here's PHP Script
photo_upload.php
<?php
$data = $_POST['photo'];
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
mkdir($_SERVER['DOCUMENT_ROOT'] . "/photos");
file_put_contents($_SERVER['DOCUMENT_ROOT'] . "/photos/".time().'.png', $data);
die;
?>
What is $selector? If it something like this:
var $selector = $(".selector");
Then you need call getCroppedCanvas() function to jQuery wrapper. Because if you write:
var canvas = $selector.cropper('getCroppedCanvas');
It calls cropper getCroppedCanvas function to DOM element, not to jQuery element.
Write something like this:
var $selector = $(".selector");
var canvas = $($selector).cropper('getCroppedCanvas');
And it will be work fine. If you want save canvas data as image on server, you can read this answer

Categories

Resources