skip to Main Content

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

2

Answers


  1. 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));
    
    Login or Signup to reply.
  2. 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>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search