I have a PHP script that computes the next value in a time series data and plots that to a graph as a PNG image. I will provide this data through AJAX, and PHP creates the PNG image. Now, how do I get the generated PNG image from PHP as an AJAX response? The code is as follows:
PHP:
<?php
$data = json_decode($_POST['data']);
// Some code to calculate the next value in this series
plotRenderRegression( $polynomialRegression, $coefficients, 0, 11 , $colorMap[ "Blue" ] );
header( "Content-Type: image/png" );
echo imagePNG( $image );
?>
JS:
$.post({
dataType: "image/png",
url: "predict.php",
data: {
sent: true,
data: "[[1,0.63151965],[2,0.58534249],[3,0.43877649],[4,0.2497794],[5,0.07730788],[6,0.08980716],[7,0.11196788],[8,0.19979455],[9,0.4833865],[10,0.9923332]]"
},
success: function (img) {
console.log(img)
i = new Image();
i.src = img;
console.log(img);
$("#imgdiv").prepend(i);
},
error: function (error, txtStatus) {
console.log(txtStatus);
console.log('error');
}
});
Console Output:
�PNG
IHDRX�Ao�NPLTE������00�������000������������333MMMfff���������������vD���IDATx��][��*�*>���o���$ ?$[��ɑq� Ι�����������2������Fp�;D33������c���وeĪF�iO̮H�����r*3'���[N
o~p#���X��ˀ���ub��T�X�,������q�.�R��}� �]��#æy����l}�
}:U���,�����'�w�W_�0S9ԡ�wl�0�עOfTc8qw��9,=�s����7��^��h�U�1b-��?��鎿G����Ag��}����7Gg��GY���R��4y� LE����8'o� �+L>A��ʻ�e�hry��سد�끷�j����`#�����)ժϜΟc-)_ck��� ���=2�W�rY�X�gY]���1�H�T�3�*�]'�V�T̼t$���ྑN��&�K���%qp�cuf���2}8����`�PA'VF%6�PoC-6!���ky����8䪏U�:������,�Ƌ�
�9Uby���W�
���共� .....
What am I doing wrong here ?
UPDATE 1:
I've changed the JS code as follows, but it still get a broken image
success: function (data) {
$('#imgdiv').html('<img src="data:image/png;base64, ' + btoa(unescape(encodeURIComponent(data))) + '" />');
}
You can't set SRC to the image itself. You can solve the problem in two ways:
1- Create a temporary file and return a link to it in your PHP file
2- base64 encode the PNG and pass it to src the way you're currently doing.
On both those ways, you'd probably have to lose the "dataType" filter of jQuery for the response to be interpreted as successful.
Example of final HTML (src set via your JavaScript Ajax):
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
// blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC />"
<img src="data:image/png;base64,[base64_encoded_png_goes_here] />"
Related
This might be a dumb question. I'm fairly new to PHP. I am trying to get a look at some echo statements from a page I'm posting to but never actually going to. I can't go directly to the page's url because without the post info it will break. Is there any way to view what PHP echos in the developer console or anywhere else?
Here is the Ajax:
function uploadImage(image) {
var data = new FormData();
data.append("image", image);
imgurl = 'url';
filepath = 'path';
$.ajax({
url: imgurl,
cache: false,
contentType: false,
processData: false,
data: data,
type: "post",
success: function(url) {
var image = $('<img class="comment_image">').attr('src', path + url);
$('#summernote').summernote("insertNode", image[0]);
},
error: function(data) {
console.log(data);
}
});
}
And here is the php file:
<?php
$image = $_FILES['image']['name'];
$uploaddir = 'path';
$uploadfile = $uploaddir . basename($image);
if( move_uploaded_file($_FILES['image']['tmp_name'],$uploadfile)) {
echo $uploadfile;
} else {
echo "Unable to Upload";
}
?>
So this code runs fine but I'm not sure where the echos end up and how to view them, there is more info I want to print. Please help!
You already handle the response from PHP (which contains all the outputs, like any echo)
In the below code you have, url will contain all the output.
To see what you get, just add a console.log()
$.ajax({
...
success: function(url) {
// Output the response to the console
console.log(url);
var image = $('<img class="comment_image">').attr('src', path + url);
$('#summernote').summernote("insertNode", image[0]);
},
...
}
One issue with the above code is that if the upload fails, your code will try to add the string "Unable to upload" as the image source. It's better to return JSON with some more info. Something like this:
// Set the header to tell the client what kind of data the response contains
header('Content-type: application/json');
if( move_uploaded_file($_FILES['image']['tmp_name'],$uploadfile)) {
echo json_encode([
'success' => true,
'url' => $uploadfile,
// add any other params you need
]);
} else {
echo json_encode([
'success' => false,
'url' => null,
// add any other params you need
]);
}
Then in your Ajax success callback, you can now check if it was successful or not:
$.ajax({
...
dataType: 'json', // This will make jQuery parse the response properly
success: function(response) {
if (response.success === true) {
var image = $('<img class="comment_image">').attr('src', path + response.url);
$('#summernote').summernote("insertNode", image[0]);
} else {
alert('Ooops. The upload failed');
}
},
...
}
If you add more params to the array in your json_encode() in PHP, you simply access them with: response.theParamName.
Here is a basic example...
HTML (Form)
<form action="script.php" method="POST">
<input name="foo">
<input type="submit" value="Submit">
</form>
PHP Script (script.php)
<?php
if($_POST){
echo '<pre>';
print_r($_POST); // See what was 'POST'ed to your script.
echo '</pre>';
exit;
}
// The rest of your PHP script...
Another option (rather than using a HTML form) would be to use a tool like POSTMAN which can be useful for simulating all types of requests to pages (and APIs)
I am working with cropper js and laravel, I cropped the image and put it into the formdata and send it to the Laravel controller by Jquery Ajax.
The problem it that I do not get data in controller. but only get an error.
the code is given below:
HTML
<button type="button" name="button" id="crop">Crop</button>
<img src="{{asset('public/img/img.jpg')}}" id="image" alt="" style="height: 500px;">
Jquery and Cropper Js Code
<script src="{{asset('public/js/jquery.min.js')}}"></script>
<script src="{{asset('public/js/cropper.min.js')}}"></script>
<script type="text/javascript">
$(document).ready(function(){
var ele = document.getElementById('image')
var cropper = new Cropper(ele);
$('#crop').on('click', function(){
var crop = cropper.getCroppedCanvas();
crop.toBlob(function(blob){
var formdata = new FormData();
console.log(blob);
formdata.append('croppedImage', blob);
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax("{{url('crop/save')}}", {
method: "POST",
data: formdata,
enctype: 'multipart/form-data',
cache: false,
processData: false,
contentData: false,
success(data){
console.log(data);
},
error(data){
console.log(data);
},
});
});
});
});
</script>
Laravel Route
Route::post('crop/save', 'CropperController#save');
Laravel Controller
public function save(Request $request){
$data = $request->croppedImage;
var_dump($data);
//Here I want to get image and upload it on the system
//But I cant Understand How
}
Error
<br />
<b>Warning</b>: Unknown: Input variables exceeded 1000. To increase the limit change max_input_vars in php.ini. in <b>Unknown</b> on line <b>0</b><br />
Please Guide me, How to done this in proper way.
Thanks in advance.
Regards,
You need to create a new image using the blob data and save that.
First, you need to get the actual contents of the image which is everything after: data:image/png;base64, or data:image/jpeg;base64,
(You can use the first part of the blob to get the extension type so you can save out the image using the same extension later.)
This will do that:
$base64Str = substr($data, strpos($data, ",")+1);
Next, you need to decode the contents as it is in base64
$file = base64_decode($base64Str);
Then, specify the path to save the new image. You can use a random generator combined with the current timestamp to get a unique name for each file.
public function generateUniqueFileName($extension)
{
return md5(uniqid(rand(), true)) . '-' . md5(microtime()) . '.' $extension;
}
$fullPath = 'public/images/' . $this->generateUniqueFileName($extension);
Finally, you can store the image to the specified path:
Storage::put($fullPath, $file);
You can try this too, since the url from your AJAX is a post request, go to app/Http/Middleware/VerifyCsrfToken.php and do this
protected $except = [
'crop/save'
];
Then in your controller you can save the image like this
public function fileUpload(Request $request){
$file = $request->file('croppedImage');
if($file) {
$file->move(public_path() .'/images', $filename);
}
}
OR
public function fileUpload(Request $request){
$file = $request->file('croppedImage');
if($file) {
Storage::disk('local')->put($filename, File::get($file));
}
}
If you are using the second way, don't forget to do this at the top of the controller'
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
The $filename variable is the name you choose to save the file with.
I have form where i can write text. I want this text to be generated on image. I have it and it works, i'm using imagepng($im). The problem is that i need to print that image, and have a "print" button. Because of header('Content-Type: image/png') i cant use html on page where i generate it so i would like to use ajax. This is my actual code which well is little mixed, i tried something with base64 but never used it and i failed. Acutally my code isnt even showing errors(shows with datatype json). I dont really know how to do it. Didn't found it anywhere. Please help i don't know what to do ;_;
Code:
<script type="text/javascript">
jQuery(function($) {
$(document).ready(function()
{
$( "#form_formularz" ).submit(function(e)
{
var data=JSON.stringify($('form').serialize())
e.preventDefault();
$.ajax({
type: 'post',
url: 'http://example.com/transfer_generator.php',
data: data,
error: function(a,b){console.log(a);console.log(b)},
success: function(cbdata){
console.log(data);
console.log(cbdata);
$('#form_image').html('<img src="data:image/png;base64,' + cbdata + '" />');
}
});
});
});
});
</script>
<div id="form_image">
</div>
EDIT:
changed "succes" to "success" and added cbdata in success: function(){
There is '
// Set the content-type
header('Content-Type: image/png');
// Create the image
$im = ImageCreateFromPNG( "image.png" );
/* adding some text, everything okay */
imagepng($im);
I tried to add echo 'base64_encode(imagepng($im));' but didnt work for this.
You have two errors in your code. Fix those before debugging further.
The success method is misspelled.
The success method has no cbdata argument. Where are you declaring this?
Try the following:
...
success: function(cbdata){
console.log(data);
console.log(cbdata);
$('#form_image').html('<img src="data:image/png;base64,' + cbdata + '" />');
}
...
EDIT: In response to your edit, do the following in your PHP file:
Remove the header statement.
You need to send back the string contents of the base64 encoded image. Something like this:
$fileName = 'my-temp-image.png';
imagepng($im, $fileName);
imagedestroy($im);
$base64Image = base64_encode(file_get_contents($fileName));
unlink($fileName);
echo $base64Image;
I'm new to jQuery/Ajax and I am trying to upload a file like so:
var fd = new FormData();
fd.append('file', file);
$.ajax({
xhr: function() {
var xhrobj = $.ajaxSettings.xhr();
if (xhrobj.upload) {
xhrobj.upload.addEventListener('progress', function(e) {
var percent = 0;
if (e.lengthComputable) {
percent = Math.floor(e.loaded / e.total * 100);
}
progressDiv.find('progress').val(percent);
progressDiv.find('b').html(percent + '%');
});
}
},
type: 'POST',
url: 'upload.php',
data: fd,
success: function(data) {
progressDiv.find('progress').val(100);
progressDiv.find('b').html('100%');
alert(data);
},
error: function() {
alert('Error uploading!');
}
});
My upload.php file looks like this:
<?php
file_put_contents('log.txt', "LOG\n");
file_put_contents('log.txt', implode(', ', $_FILES) . "\n", FILE_APPEND);
$target = 'upload/' . basename($_FILES['file']['name']);
if (move_uploaded_file($_FILES['file']['tmp_name'], $target)) {
file_put_contents('log.txt', "SUCCESS\n", FILE_APPEND);
} else {
file_put_contents('log.txt', "FAILURE\n", FILE_APPEND);
}
?>
The problem is that the progress bars are remaining at 0 and the no alert ever appears. Also nothing is being written to the log file, meaning that upload.php is not even being called.
What am I doing wrong?
EDIT:
After searching for a while I stumbled across this nifty little question: Submitting a file with jQuery.ajax gives TypeError
So adding contentType: false and processData: false seems to have done something. Now I get the alert "Error uploading", but I still don't think upload.php is being called as nothing is being written to log. Commenting out the xhr stuff after making those changes allows the upload to complete. Now the question becomes what is wrong with the xhr stuff?
What is 'log'?
file_put_contents('log', "LOG\n");
I bet if you looked at your webserver error log the PHP script would be found to be choking on trying to write to 'log'.
EDIT
Here's an existing question that appears to show correctly how to do what you're trying to do. If you're still not getting the result you expect, I would still suspect there's something wrong with your file paths. Full error reporting should clarify the issue
update progress bar using ajax request seconds
I have a site with a giant portfolio with a ton of high-res images.
I do not want to resize these images, but I would like to be able to pull them in async.
Come forth jQuery .ajax
But my code is wrong, somehow. What it does is seem to pull in the page, instead of the image "src"
Can you help:
// Load in the images via ajax:
var $imgs = $('.ajax-image');
$imgs.each(function(i){
var $imgsrc = $(this).attr('src');
var $url = '/php/pull-image.php?i=' + $imgsrc;
$.ajax({
url : $url,
mimeType: "text/plain",
processData : false,
cache: false,
success: function (html) {
$(this).attr('src', html);
}
});
});
and the PHP:
$path = $_GET['i'];
$type = pathinfo($path, PATHINFO_EXTENSION);
$data = file_get_contents($path);
echo 'data:image/' . $type . ';base64,' . base64_encode($data);
Image tags are simply: <img src="http://example.com/images/image.ext" />
What am I doing wrong here? and how can I fix it?
As I mentioned in my comment, I don't see how this would do what you want but to address your current problem: It is probably caused because of this in the context of the success function, is not the same as the this in the context of your each() function.
You should save the element so that you can access it in the success function:
$imgs.each(function(i){
var el = $(this),
$imgsrc = el.attr('src'),
$url = '/php/pull-image.php?i=' + $imgsrc;
$.ajax({
url : $url,
mimeType: "text/plain",
processData : false,
cache: false,
success: function (html) {
el.attr('src', html);
}
});
});
Edit: There is no real need to use ajax / php here to set the source of the image. You could also generate some images in javascript (in batches), add an onload() function for the images and set the source of your html elements when they are loaded and then get the next batch. See for example this question: JavaScript: Load an image from javascript then wait for the "load" event of that image
Your php page is getting an error because you are not passing in anything for parameter i. Your php is therefore throwing a 404 error - a full HTML response.
I think you have a javascript syntax error that is causing this:
url : '/php/pull-image.php?i=' . $imgsrc,
Replace this line with:
url : '/php/pull-image.php?i=' + '<?php echo json_encode($imgsrc); ?>' ,