Save image on server error - javascript

I have an ajax fuction to take a div and make it picture and then post it on php for saving it .
<script>
$("#capture").click(function() {
html2canvas([document.getElementById('printableArea')], {
onrendered: function (canvas) {
var imagedata = canvas.toDataURL('image/png');
var imgdata = imagedata.replace(/^data:image\/(png|jpg);base64,/, "");
//ajax call to save image inside folder
$.ajax({
url: 'save_image.php',
data: {
imgdata:imgdata
},
type: 'post',
success: function (response) {
console.log(response);
$('#image_id img').attr('src', response);
}
});
}
})
});
</script>
Then i have the save image php to save it on server
<?php
$imagedata = base64_decode($_POST['imgdata']);
$filename = md5(uniqid(rand(), true));
//path where you want to upload image
$file = '/home/a7784524/public_html/barcodeimage/'.$filename.'.png';
$imageurl = 'http://panosmoustis.netai.net/barcodeimage/'.$filename.'.png';
file_put_contents($file,$imagedata);
echo $imageurl;
?>
My problem is although the image is saved on path when i try to open it i get the error the image cannot be displayed because it contains errors
Thank you

#aristeidhsP Please check file_put_contents return; is the image really created ?
If so you, have to check the content of $imagedata: have you correctly stripped the extra stuff from the image data (your regex may not fire on jpeg or gif extension).
Hope this helps

Related

Saving images uploaded using ImagesLoader

I am trying to wire up the ImagesLoader plugin, which allows uploading multiple images. It has a nice drag-n-drop UI but I just can't figure out how to get the images that were uploaded. I cannot find any documentation.
Link to the plugin page: ImagesLoader
Here is the javascript from the demo:
<script type="text/javascript">
// Ready
$(document).ready(function () {
// Create image loader plugin
var imagesloader = $('[data-type=imagesloader]').imagesloader({
minSelect: 3
,imagesToLoad: [{"Url":"./img/Nespresso001.jpg","Name":"Nespresso001"},{"Url":"./img/Nespresso002.jpg","Name":"Nespresso002"}]
});
//Form
$frm = $('#frm');
// Form submit
$frm.submit(function (e) {
var $form = $(this);
var files = imagesloader.data('format.imagesloader').AttachmentArray;
var il = imagesloader.data('format.imagesloader');
if (il.CheckValidity())
alert('Upload ' + files.length + ' files');
e.preventDefault();
e.stopPropagation();
});
});
The images are saved in the object "files". Here is a screen shot of the contents from the inspector:
I tried converting to json and posting, but that only generates an error.
$.ajax({
url: 'process-images.php',
type: 'POST',
data: JSON.stringify(files),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
cache: false,
error: function() {alert("ERROR");},
success: function() {alert("OK");}
});
The rest of the code works just like the demo. Looks like everything needed for the uploaded images is stored in "files". I just need to get the data back to php and I can pull it apart from there. But right now, the original submit code just dies or my addition aborts with an error.
THANKS!
I hope it is not too late to answer.
You just need to loop through the base64 encoded image object, decoding and saving each image to the disk.
// Sample code
foreach(json_decode($request->input('files')) as $file) {
$name = $file->FileName
$imagePath = storage_path('app/public/images/');
file_put_contents($imagePath.$name, base64_decode($file->Base64));
}

Uploading image using ajax

I have a variables src and image,
var src = $("#img_tag").attr('src');
var image = new Image();
I want to pass this image variable to a public function in php to upload. What is it that exactly that I need to pass, is it the src, the base64, the image itself as new FormData ?
Right now I have:
var data = new FormData();
var src = $("#img_tag").attr('src');
var image = new Image();
data.append('Image', image);
console.log(data);
$.ajax({
url: "/products/image_upload",
type: "POST",
data: data,
processData: false,
contentType: false,
success: function (msg) {
console.log(msg+"---Image was uploaded");
}
error: function(err) {
console.log(err);
}
});
In my view:
public function image_upload() {
$this->autoRender = false;
echo json_encode($this->data);
if($this->request->is('post'))
{
if(!empty($_FILES['Image']['name'])) {
$file = $_FILES['Image'];
echo json_encode($file);
$ext = substr(strtolower(strrchr($file['name'], '.')), 1);
$arr_ext = array('jpg', 'jpeg', 'gif', 'png');
$temp = explode(".", $file['name']);
$newfilename = $_FILES['Image']['name'];
if(in_array($ext, $arr_ext))
{
if(move_uploaded_file($file['tmp_name'], WWW_ROOT . 'img/product-uploads' . DS . $newfilename))
{
echo json_encode("Image uploaded properly");
return json_encode($_FILES);
}
}
}
}
}
And getting:
{"Image":"[object HTMLImageElement]"}---Image was uploaded
BUT IMAGE IS NOT UPLOADED
If you take a look at the FormData.append doc, you will see that the second argument takes a string or a blob.
So passing an HTMLImageElement isn't going to work, if you cant get the image as a Blob or a File using a FormData object doesn't really help.
Since you're trying to upload the src of #img_tag, this will only really work if it is the base64 encoded image.
In this case use data.append('Image', src); and read the data from $_POST['Image'] then clean it up and decode it.
If the image src is a regular url, use $_POST['Image'] with curl to download the image to your server.
I got a bit of a research, and found this article super helpful. (Thanks to that)
I managed to upload an image file to a directory in my server from an image src by getting the base64 encoded image, passed for the controller to decode and upload. (Also thanks to Musa, DanielO, and Rory McCrossan)
In Controller: Code from this article. (I added a custom filename in a datetime format)
public function additional_image_upload() {
$this->autoRender = false;
$base64 = $this->request->data['base64'];
$product_id = $this->request->data['id'];
$baseFromJavascript = $base64;
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $baseFromJavascript));
$t = microtime(true);
$micro = sprintf("%06d",($t - floor($t)) * 1000000);
$date_tmp = new DateTime( date('Y-m-d H:i:s.'.$micro, $t) );
$date = $date_tmp->format("Y-m-d_his.u");
$filepath = WWW_ROOT . 'img/product-uploads' . DS ."$date.jpg"; // or image.jpg
file_put_contents($filepath,$data);
}
In Script: (I passed the base64 encoded image for the controller to handle)
var src = $(this).attr('src');
$.ajax({
url:"/products/additional_image_upload",
data:{
"id": "<?= $id; ?>",
"base64": src
},
type:"POST",
success: function(msg) {
console.log(msg."---Img uploaded");
},
error: function(error) {
console.log(error);
}
});
And all was working great. Added this to help future readers.

Why is PHP Session variable changing to something unrelated when retrieved in an AJAX call?

I have a page at example.com/add-results.php with a large form where one of the "fields" is this area below where people can upload an image. Standard behavior with a "Choose Image" button, then when you choose it, an "Upload" button appears. Then you click that and a preview of the now-uploaded-the-server image appears with a "Remove/Change" button.
Important note here how the default src for the preview image is "no-image.png" (this comes into play later)...
<label class="caption" for="">Pool Image </label> (OPTIONAL - You can add one later if you don't have one now)<br>
<span>for testing: <?php echo $_SESSION['poolid'];?></span>
<div id="preview"><img id="image" src="no-image.png" /></div>
<label for="uploadImage" id="custom-file-upload">
Choose Image
</label>
<span id="file-selected"></span>
<input id="uploadImage" type="file" accept="image/*" name="image" />
<input id="button" type="button" value="Upload" class="displaynone webkit">
<input id="remove-image" class="displaynone" type="button" value="Remove/Change">
<div id="err"></div>
Also included on the add-results.php page is this javascript file which makes an AJAX call...
$(document).ready(function () {
$("input:file").change(function (){
$( "#button" ).show();
});
$('#uploadImage').bind('change', function() { var fileName = ''; fileName = $(this).val(); $('#file-selected').html(fileName); });
$("#button").click(function(){
var imageData = new FormData();
imageData.append('image', $('#uploadImage')[0].files[0]);
//Make ajax call here:
$.ajax({
url: "/upload-image-results-ajax.php",
type: 'POST',
processData: false, // important
contentType: false, // important
data: imageData,
beforeSend : function() {
$("#err").fadeOut();
},
success: function(result) {
if(result=='invalid file') {
// invalid file format.
$("#err").html("Invalid File !").fadeIn();
} else {
// view uploaded file.
$("#image").attr('src', '/'+result);
/* $("#preview").html(data).fadeIn();*/
/* $("#form")[0].reset(); */
//show the remove image button
$('#file-selected').empty();
$( "#remove-image" ).show();
$( "#custom-file-upload" ).hide();
$( "#uploadImage" ).hide();
$( "#button" ).hide();
}
},
error: function(result) {
$("#err").html("errorcity").fadeIn();
}
});
});
$("#remove-image").click(function(){
//Make ajax call here:
$.ajax({
url: "/remove-image-results.php",
type: 'POST',
processData: false, // important
contentType: false, // important
success: function(result) {
if(result=='gone') {
$("#image").attr('src', '/images/no-image.png');
$('#file-selected').empty();
$( "#custom-file-upload" ).show();
$( "#remove-image" ).hide();
$( "#uploadImage" ).hide();
$( "#button" ).hide();
} else {
}
},
error: function(result) {
$("#err").html("error").fadeIn();
}
});
});
//deleting uploaded image (if one exists) if user cancel's out of Add Results screen
$("#cancel-and-remove-image").click(function(){
//Make ajax call here:
$.ajax({
url: "/remove-image-results.php",
type: 'POST',
processData: false, // important
contentType: false, // important
success: function(result) {
},
error: function(result) {
}
});
});
});
Finally, this is a page called upload-image-results-ajax.php which performs the actual upload task called by the AJAX call above...
<?php
require_once("includes/session.php");
$poolid=$_SESSION['poolid']; //lowercase it first so we get exact matches
$valid_extensions = array('jpeg', 'jpg', 'png', 'gif'); // valid extensions
if(isset($_FILES['image'])) {
$img = $_FILES['image']['name'];
$tmp = $_FILES['image']['tmp_name'];
// get uploaded file's extension
$ext = strtolower(pathinfo($img, PATHINFO_EXTENSION));
//checking if image exists for this pool and removing if so, before adding new image in its place
if(file_exists("uploads/results/".$poolid.".png")) {
unlink("uploads/results/".$poolid.".png");
}
// checks valid format
if(in_array($ext, $valid_extensions)) {
//re-size the image and make it a PNG before sending to server
$final_image = $poolid . ".png";
$path = "uploads/results/".strtolower($final_image);
$size = getimagesize($tmp);
$ratio = $size[0]/$size[1]; // width/height
if( $ratio > 1) {
$width = 200;
$height = 200/$ratio;
}
else {
$width = 200*$ratio;
$height = 200;
}
$src = imagecreatefromstring(file_get_contents($tmp));
$dst = imagecreatetruecolor($width,$height);
imagecopyresampled($dst,$src,0,0,0,0,$width,$height,$size[0],$size[1]);
imagedestroy($src);
imagepng($dst, $path); // adjust format as needed
imagedestroy($dst);
echo $path ."?".rand(1,32000);
} else {
echo 'invalid file';
}
}
?>
Note how it says "$poolid=$_SESSION['poolid'];". That's the key to all this. This session ID definitely is set on the add-results.php page with an actual poolid, like p0902ftel7
QUICK ASIDE: Since I know someone would ask, let's get this out of the way. A session definitely IS started at the top of add-results.php and also at the top of the page above using an include of session.php, which contains simply:
<?php
session_start();
?>
The final image location/url should be in the format of "example.com/uploads/results/(poolid).png"
So an example using an actual poolid would be: "example.com/uploads/results/p0902ftel7.png"
So as long as $_SESSION['poolid'] is set (which again it is), the poolid will be set and the URL of the image will correct.
Now, when I upload an image, it does upload the image to the server, but instead of being named "p0902fte17.png", it is named "no-image.png". So the full URL of the uploaded image is something like: example.com/uploads/results/no-image.png.png?22555
FYI, the "?22555" is just a random number being added to help with cached images issues when the image is previewed.
I am completely baffled by this behavior and am praying someone knows what might be happening. I've lost about 8 hours looking into this now. I can't fathom how the value of $_SESSION['poolid'] changes from an actual id (like p0902fte17) to "no-image.png" (the default image src from add-results.php).
Any ideas?

require_once() or AJAX causing php script to run twice

I'm making a step by step form that stores session variables as you follow the steps.
On one step I have a file upload that previews the image and shows an upload button, which when pressed calls a php script that needs to modify a $_SESSION variable, as well as echo the path to the uploaded file.
When I test it in my debugger without require_once('config.php'), it works exactly as I anticipate, showing the image and it's filename, however, for some reason when I include the config file, when I iterate through it in my debugger, it appears to run the php script twice, it correctly updates the session variable, but the filename isn't echoed anymore and the data is lost before it reaches the frontend.
I can't tell if the mistake is in the config.php file, or in the AJAX call, or maybe somewhere else where I'm missing.
The markup ('step4.php'):
<form method="post" action="step5.php">
<span id="newfile">
<input type="file" name="uploaded_file" id="imageupload" accept=".jpg, .jpeg, .png">
<img alt="Preview Loading..." id="imagepreview">
</span>
<!-- The submit button is elsewhere before the end of the form, it acts as a next button -->
</form>
The javascript function:
$(document).on('click', '#uploadbutton', function(e) {
e.preventDefault();
//Grab upload elements and and file
var uploadbutton = this;
var uploader = document.getElementById('imageupload');
var file = document.getElementById('imageupload').files[0];
//Hide the upload elements
uploadbutton.parentNode.removeChild(uploadbutton);
uploader.parentNode.removeChild(uploader);
//Make the form and pass it to server
var formData = new FormData();
formData.append('file', file); //$_FILES['file']
$.ajax({
url: 'uploadfile.php',
type: 'POST',
data: formData,
processData: false,
contentType: false
})
.done(function(data) {//Data is the relative path to the file
//Hide the old content
document.getElementById('newfile').innerHTML = '';
//Show the new image
var text = document.createTextNode('Uploaded File: '+data.replace('temp/', '', data));
var br = document.createElement("br");
var imgElement = document.createElement("IMG");
imgElement.setAttribute('src', data);
document.getElementById('newfile').appendChild(text);
document.getElementById('newfile').appendChild(br);
document.getElementById('newfile').appendChild(imgElement);
})
.fail(function() {
alert("Error uploading the file. Hit refresh and try again.");
});
});
'uploadfile.php': (the one that my debugger shows gets executed twice...)
<?php
//require_once('config.php'); //THE PROBLEM?
if($_FILES) {
//Get the uploaded file information
$name_of_uploaded_file = $_FILES['file']['name'];
//Actually upload the file to the server!
$upload_folder = 'temp/'; //Make a file named temp
$path_of_uploaded_file = $upload_folder.$name_of_uploaded_file;
$tmp_path = $_FILES["file"]["tmp_name"];
if(is_uploaded_file($tmp_path)) {
copy($tmp_path,$path_of_uploaded_file);
$_SESSION['step4filepath'] = $path_of_uploaded_file;
echo $path_of_uploaded_file;
}
}
?>
'config.php': the one that screws stuff up when it's included
<?php
session_start();
//Initialize session data
if(empty($_SESSION)) {
if(!isset($_SESSION['step4filepath'])) {
$_SESSION['step4filepath'] = '';
}
}
//Update session data
if($_SERVER['REQUEST_METHOD'] === 'POST') {
if($_SESSION['currentPage'] == 4) {
//input for step 4, we just want filename if they submit the form
$_SESSION['step4filepath'] = $_POST['step4filepath'];
}
//Enable us to hit the back button!
header("Location: " . $_SERVER['REQUEST_URI']);
}
?>
Totally lost on this.
May be this? Why that line is there on your config file?
header("Location: " . $_SERVER['REQUEST_URI']);
It looks like config.php is replacing the value of $_SESSION['step4filepath'] with $_POST['step4filepath'], rather than leaving it as $path_of_uploaded_file.
EDIT
As mentioned elsewhere, header() will be causing a reload. My answer is irrelevant as config.php is called before the var is set.
Solution 1
Replace
$(document).on('click', '#uploadbutton', function(e) {
To
$(document).off('click').on('click', '#uploadbutton', function(e) {
Solution 2: See below sample code
$(document).on("click", "#someID", function(e) {
$(this).attr("disabled","disabled");
// Disabling the input stops the event from firing multiple times.
var targetObj = $(this);
// targetObj can be used within the $.POST function, not $(this)
var myVariable = "Hello world";
$.post("/DoSomethingAJAXY.php", { variable1: myVariable },
function(data, status){
if (status == "success") {
// Do something
}
$(targetObj).removeAttr("disabled");
// Re-enable the event input trigger
});
}

Can't save image via HTML canvas

I'm having difficulties saving my canvas. I'm new to javascript so I think it could be a syntax issue.
I've got some vars saved in a function:
var imageView = document.getElementById("imageView");
var canvasData = imageView.toDataURL("image/png");
var postData = "canvasData="+canvasData;
If I add the following line it displays the image correctly:
imgData = $('#i').append($('<img/>', { src : canvasData }));
However, I have another function that I want to pass the base64 code in so I added:
var the_data = "test= "+imageView.toDataURL("image/png");
It does print out a base64 code, but just the blank canvas (not with the drawing the user has added).
If I add the following it doesn't work:
var the_data = "test= "+canvasData;
What am I doing wrong?
This is a basic jsfiddle of what I'm trying to do: http://jsfiddle.net/sMSeX/
Just a little hint from my side for uploading HTML5 canvas image data:
I am working on a project for a print-shop and had some problems due to uploading images to the server that came from an HTML5 canvas element. I was struggling at least for one hour and I did not get it to save the image correctly on my server.
I get the image data as Base64 decoded from the canvas element via
var can = document.getElementsByTagName('canvas');
var dataURL = can[0].toDataURL("image/jpg");
//dataURL = dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
console.log('data url: '+dataURL);
Once I set the
contentType option of my jQuery ajax call to 'application/x-www-form-url-encoded' :
$.ajax({
url: 'index.php?page=upload-image',
type: 'post',
contentType: 'application/x-www-form-urlencoded',
//data: '{ "imageData" : "' + dataURL + '" }',
data: dataURL,
beforeSend: function() {
$('.text-danger').remove();
},
complete: function() {
},
success: function(json) {
console.log('upload complete');
}
});
everything went the right way and the base64-encoded data was interpreted correctly and successfully saved as an image.
Maybe someone helps that!

Categories