Can you please take a look at this code and let me know why I am not able to get a PHP generated captcha (image) by Ajax call in jQuery?
What I have in captcha.php
is simply this
<?php
session_start();
$random_alpha = md5(rand());
$captcha_code = substr($random_alpha, 0, 6);
$_SESSION["captcha_code"] = $captcha_code;
$target_layer = imagecreatetruecolor(70,30);
$captcha_background = imagecolorallocate($target_layer, 255, 160, 119);
imagefill($target_layer,0,0,$captcha_background);
$captcha_text_color = imagecolorallocate($target_layer, 0, 0, 0);
imagestring($target_layer, 5, 5, 5, $captcha_code, $captcha_text_color);
header("Content-type: image/jpeg");
imagejpeg($target_layer);
?>
and this is my jQuery Ajax request
$(function() {
var getCaptcha = $.ajax({
type: "GET",
url: 'captcha.php',
cache: false,
dataType: 'image/jpeg',
success: function (data) {
$("#captcha").attr("src", 'data:image/jpeg;base64,' data);
}
});
getCaptcha.fail(function (jqXHR, textStatus) {
console.log("Request failed: " textStatus);
});
});
on my console I am getting this error
Request failed: parsererror
and in source code the src of #captcha
is showing unknown!
CodePudding user response:
The PHP script is sending image headers not the base64 encoded data that you are expecting so try:
<?php
session_start();
$random_alpha = md5(rand());
$captcha_code = substr($random_alpha, 0, 6);
$_SESSION["captcha_code"] = $captcha_code;
$target_layer = imagecreatetruecolor(70,30);
$captcha_background = imagecolorallocate($target_layer, 255, 160, 119);
imagefill($target_layer,0,0,$captcha_background);
$captcha_text_color = imagecolorallocate($target_layer, 0, 0, 0);
imagestring( $target_layer, 5, 5, 5, $captcha_code, $captcha_text_color);
# create a temp file to save the image
$tmp=tempnam( sys_get_temp_dir(), 'captcha' );
# save the image & then read it's contents
imagejpeg( $target_layer, $tmp );
$data=file_get_contents( $tmp );
# clean up
imagedestroy( $target_layer );
unlink( $tmp );
# send the base 64 data string
exit( base64_encode( $data ) );
?>
And then modify the ajax slightly to remove the expected dataType
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
<script src='//code.jquery.com/jquery-latest.js'></script>
<script>
$(function() {
var getCaptcha = $.ajax({
type: "GET",
url: 'captcha.php',
cache: false,
success: function (data) {
$("#captcha").attr("src", 'data:image/jpeg;base64, ' data );
}
});
getCaptcha.fail(function (jqXHR, textStatus) {
console.log("Request failed: " textStatus);
});
});
</script>
</head>
<body>
<img id='captcha' />
</body>
</html>
To accomplish the same without encoding in PHP ( as per your question in the comment below ) - Yes, it can be done. The following omits the jQuery code as I do not use jQuery and wouldn't know the methods to use so instead some very simple vanilla javascript and your original PHP code will work.
<?php
session_start();
$random_alpha = md5(rand());
$captcha_code = substr($random_alpha, 0, 6);
$_SESSION["captcha_code"] = $captcha_code;
$target_layer = imagecreatetruecolor(70,30);
$captcha_background = imagecolorallocate($target_layer, 255, 160, 119);
imagefill( $target_layer,0,0,$captcha_background );
$captcha_text_color = imagecolorallocate($target_layer, 0, 0, 0);
imagestring( $target_layer, 5, 5, 5, $captcha_code, $captcha_text_color);
header("Content-type: image/jpeg");
exit( imagejpeg( $target_layer ) );
?>
And the clientside:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8' />
<title></title>
<script>
fetch('captcha.php')
.then( r=>r.blob() )
.then( data=>{
document.getElementById('captcha').src=URL.createObjectURL( data );
})
</script>
</head>
<body>
<img id='captcha' />
</body>
</html>
CodePudding user response:
Looks like there is a slight disconnect between what you return from the ajax call and what you try to display.
This sends out the jpeg in its natural binary form.
header("Content-type: image/jpeg");
imagejpeg($target_layer);
Here you treat it like an base64_encoded
image.
$("#captcha").attr("src", 'data:image/jpeg;base64,' data);
At that point you might want to do an actual base64_encode()
and send that back or encode it on the JS side.
For example
$("#captcha").attr("src", 'data:image/jpeg;base64,' btoa(data));