Skip to content
Advertisement

Issue on Getting PHP Generated Image By jQuery Ajax Call

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!

enter image description here

Advertisement

Answer

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>
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement