0

I am building an in-house app for Client Relationship Management.

This app is fairly straight forward. It collects client information and stores it for later use.

One part of the information collected is an image of the clients photo identification. I am storing this image in its own table in mySQL database.

I have been looking for a way to display the image in a small preview window along side the clients information (name, address, etc). What I am finding for possible solutions are very old and depreciated at this point, or refer to displaying an image where just the URL of the file is stored in the database and the image itself is saved in a folder on the server.

The code I currently have does not display anything in the HTML but blank space. I did have one version before this that displayed the raw data from the BLOB, but it was crashing everything so I did not keep it to show you here.

My question is, is there a resource someone can point me to that is specifically about how this type of information is used by a web browser and how to organize it appropriatly for display? OR, if this is all wrong for some reason, can someone point me towards documentation that is a better way to do this? I am not experienced with any of this, and have trouble searching for answers sometimes due to lack of correct terminology.

The table looks like:

TABLE NAME = "photoid"
 row 1 = "id" (auto increment)
 row 2 = "name" (varchar)
 row 3 = "mime" (varchar)
 row 4 = "size" (bigint)
 row 5 = "data" (medium blob)
 row 6 = "created" (datetime)
 row 7 = "client_id" (varchar)

The HTML:

<img width="400" height="200" src="<?php include ('client_display_photoid.php');?>" />

The PHP:

<?php include ('connect.php');?>

<?php
$client_id = htmlspecialchars($_POST['client_id']);

// prepare stmt, bind param, execute
$stmt = $conn->prepare("SELECT mime, name, size, data FROM photoid WHERE client_id = ?");
$stmt->bind_param("s", $client_id);
$stmt->execute();

// bind results
$stmt->bind_result($mime, $name, $size, $data);


// Print headers
header("Content-Type: $mime");
header("Content-Length: $size");
header("Content-Disposition: attachment; filename = $name");

// Print data
echo $data;
?>

<?php include ('disconnect.php');?>

EDIT 1: After reviewing the comments, I was able to get rid of the "blank space" that was displaying by removing the open PHP tags. I also looked at the link provided and changed my code as follows.

HTML:

<img width="300px" height="150px" src="data:image/jpeg;base64,<?php echo base64_encode( $data ); ?>" />

PHP:

<?php 
include ('connect.php');

$stmt = $conn->prepare("SELECT data FROM photoid WHERE client_id = ?");
$stmt->bind_param("s", $client_id);
$stmt->execute();

$stmt->bind_result($data);

include ('disconnect.php');
?>

The following is what is now displayed when I try to display the image:

<img width="300px" height="150px" src="data:image/jpeg;base64," />

EDIT 2:

I have tried the following code... HTML:

<img src='client_display_photoid.php?client_id=182' />

PHP:

<?php 
include ('connect.php');

$sql='select `mime`,`data` from `photoid` where `client_id` = ?';
$stmt=$conn->prepare( $sql );
if( $stmt ){

    $stmt->bind_param('s', $client_id );
    $result=$stmt->execute();
    $stmt->store_result();

    if( $result && $stmt->num_rows==1 ){

        $stmt->bind_result( $mime, $data );
        $stmt->fetch();
        $stmt->close();


        $data=base64_decode( $data );
        #$mime=image_type_to_mime_type( $mime );
        $oImg = imagecreatefromstring( $data );

        switch( $mime ){
            case IMAGETYPE_JPEG:
                header( 'Content-Type: image/jpeg' );
                imagejpeg( $oImg );
            break;
            case IMAGETYPE_PNG:
                header( 'Content-Type: image/png' );
                imagepng( $oImg );
            break;
            case IMAGETYPE_GIF:
                header( 'Content-Type: image/gif' );
                imagegif( $oImg );
            break;
        }
        imagedestroy( $oImg );
    }
}

include ('disconnect.php');
?>

All I get back in the browser is:

<img src='client_display_photoid.php?client_id=182' />
inkslinger
  • 93
  • 1
  • 15
  • I think this should help you: https://stackoverflow.com/q/7793009/2191572 – MonkeyZeus Jan 18 '18 at 15:31
  • I would suggest that `` is incorrect and unlikely to produce what you are hoping for ~ though without seeing it's content it is hard to know. The storing of blobs in the db does mean the db will potentially grow to a disproportionately large size compared to the number of records ~ why is it a bad thing to just store the path to the image? – Professor Abronsius Jan 18 '18 at 15:32
  • "*refer to displaying an image where just the URL of the file is stored in the database and the image itself is saved in a folder on the server*" is usually the preferred method, much easier to manipulate, doesn't require a database for resource grabs, readable/manageable code. And as @RamRaider said, less db bloat from all the blobs. – IncredibleHat Jan 18 '18 at 15:33
  • Specifically, https://stackoverflow.com/a/7795225/2191572 would help you achieve what you need with minimal change to your code – MonkeyZeus Jan 18 '18 at 15:35
  • Possible duplicate of [How to retrieve images from MySQL database and display in an html tag](https://stackoverflow.com/questions/7793009/how-to-retrieve-images-from-mysql-database-and-display-in-an-html-tag) – MonkeyZeus Jan 18 '18 at 15:35
  • Side note: You don't need `htmlspecialchars()`, you're using a prepared statement already and it doesn't do what you think you want it to do. – Funk Forty Niner Jan 18 '18 at 15:36
  • As well, passing it to javascript too (alternative question/answer to Monkey's links): https://stackoverflow.com/a/21227124/2960971 – IncredibleHat Jan 18 '18 at 15:38
  • Another side note: You have some close and open php tags `?> ` as the very last characters of your script. – IncredibleHat Jan 18 '18 at 15:54
  • I am storing the images as BLOB in the database itself to keep everything in one place and to make backups easier for me. Each client will have just the one image attached to their file, so I don't feel database bloat will be an issue. – inkslinger Jan 18 '18 at 15:59
  • The PHP shown - is that the contents of `client_display_photoid.php`? – Professor Abronsius Jan 18 '18 at 16:15
  • Yes, the PHP shown is “client_display_photoid.php” – inkslinger Jan 18 '18 at 16:27
  • I have edited the original post and added the changes I have tried. I am still not able to display the image. – inkslinger Jan 18 '18 at 17:13

2 Answers2

0

The following ought to help get this sorted for you - the db stores the base64 encoded data as a blob and creates the image on the fly using php and imagecreatefromstring. The below code worked for me in test so with care you should be able to modify this to work in your environment. One difference is the use of an integer mimetype in the db rather than a string.

The above $mime is an integer but using image_type_to_mime_type on that returned value would yield the mime type string.. It just means you have to modify that bit to work with strings rather than ints.

mysql> describe photoid;
+-----------+---------------------+------+-----+---------------------+----------------+
| Field     | Type                | Null | Key | Default             | Extra          |
+-----------+---------------------+------+-----+---------------------+----------------+
| id        | int(10) unsigned    | NO   | PRI | NULL                | auto_increment |
| name      | varchar(50)         | NO   |     | NULL                |                |
| mime      | tinyint(3) unsigned | NO   |     | NULL                |                |
| size      | int(11)             | NO   |     | NULL                |                |
| data      | mediumblob          | YES  |     | NULL                |                |
| created   | datetime            | NO   |     | 0000-00-00 00:00:00 |                |
| client_id | varchar(50)         | NO   | MUL | NULL                |                |
+-----------+---------------------+------+-----+---------------------+----------------+

enter image description here


<?php

    /* display profile picture: photoid.php  */

    $client_id=!empty( $_GET['client_id'] ) ? filter_input( INPUT_GET, 'client_id', FILTER_SANITIZE_STRING ) : false;


    if( $client_id ){

        $dbhost =   'localhost';
        $dbuser =   'root';
        $dbpwd  =   'xxx';
        $dbname =   'xxx';
        $db     =   new mysqli( $dbhost, $dbuser, $dbpwd, $dbname );


        $sql='select `mime`,`data` from `photoid` where `client_id` = ?';
        $stmt=$db->prepare( $sql );
        if( $stmt ){

            $stmt->bind_param('s', $client_id );
            $result=$stmt->execute();
            $stmt->store_result();

            if( $result && $stmt->num_rows==1 ){

                $stmt->bind_result( $mime, $data );
                $stmt->fetch();
                $stmt->close();


                $data=base64_decode( $data );
                #$mime=image_type_to_mime_type( $mime );
                $oImg = imagecreatefromstring( $data );

                switch( $mime ){
                    case IMAGETYPE_JPEG:
                        header( 'Content-Type: image/jpeg' );
                        imagejpeg( $oImg );
                    break;
                    case IMAGETYPE_PNG:
                        header( 'Content-Type: image/png' );
                        imagepng( $oImg );
                    break;
                    case IMAGETYPE_GIF:
                        header( 'Content-Type: image/gif' );
                        imagegif( $oImg );
                    break;
                }
                imagedestroy( $oImg );
            }
        }
    }

?>

Within the html you can call this like this:

<img src='photoid.php?client_id=5a60cc8780ee6' />

ie:

<?php
    #include __DIR__ . '/db.php';
?>
<!doctype html>
<html>
    <head>
        <meta charset='utf-8' />
        <title>Display the PHP generated image</title>
    </head>
    <body>
        <!--

            The main content on the page will be, I guess, generated using PHP
            so a db lookup to get the records and render appropriate content

            $res=$db->query('select * from blah');
            while( $rs=$res->fetch_object() ){
                echo "content
                <img src='photoid.php?client_id={$rs->id}' />";
            }
        -->

        <img src='photoid.php?client_id=5a60e11e02d18' />
    </body>
</html>
Professor Abronsius
  • 33,063
  • 5
  • 32
  • 46
0

I messed around with this a bunch today and found that changing my PHP to the following allowed me to just use a simple PHP INCLUDE in the HTML to display the image as desired.

It looks like the WHILE statement was what did the trick. I also used some of the suggestions provided and took advantage of ECHO-ing HTML within the PHP code.

Much thanks to everyone who commented and helped.

PHP:

<?php
if (!empty($_POST['client_id'])) {
    // connect to database
    include ('connect.php');

    // prepare stmt, bind param, execute
    $stmt = $conn->prepare("SELECT data FROM photoid WHERE client_id = ?");
    $stmt->bind_param("s", $client_id);
    $stmt->execute();

    // bind results
    $stmt->bind_result($data);

    while ($stmt->fetch()) {
    }

    echo '<img width="300" src="data:image/jpeg;base64,'.base64_encode( $data ).'"/>';

    // close statement
    $stmt->close();

    // disconnect from databse
    include ('disconnect.php');
}
?>
inkslinger
  • 93
  • 1
  • 15