Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    Regular Coder
    Join Date
    Mar 2007
    Location
    Quebec
    Posts
    261
    Thanks
    6
    Thanked 7 Times in 7 Posts

    Broken image when called from DB

    Hi,

    I've been working on an image upload script. I've got the upload part working correctly, but I can't seem to properly recall the image from the database and show it. I've been following this tutorial: http://www.spoono.com/php/tutorials/tutorial.php?id=42

    Basically, I've got an image upload form that uploads image, opens & reads image, base64_encodes the image and inserts it into a longtext MySQL field.

    Then I've got getImage.php, whose job is to pick out the appropriate image (given through the id param - getImage.php?id=x) from the database, decoded the data and then echo it.

    Finally, I've got view.php whose job is to actually show the image, through the normal HTML call like so:
    Code:
    <img src="getImage.php?id=2" />
    The problem is that view.php doesn't show the image, or can't find it. (Shows the broken image logo). I can't figure out why. At one point, it was working, but then I switched databases and BOOM, broken again :/

    Here are the files (all are basic/lacking security... 'cause their basic atm :P)

    uploadImage.php
    PHP Code:
    <?php
    include_once("/home/flawclan/public_html/xxxxx/class/startclasses.php");
    ######################################################
    #getImage.php v1.0                                   #
    #read file, encode it, decode it and display it again#
    ######################################################
    $upload $_POST['upload'];
    if(isset(
    $upload)){
        
    //PHP file upload vars
        
    $fileError $_FILES['imageFile']['error'];
        
    $fileName $_FILES['imageFile']['name'];
        
    $fileSize $_FILES['imageFile']['size'];
        
    $fileType $_FILES['imageFile']['type'];
        
    $fileTempName $_FILES['imageFile']['tmp_name'];    
        
    //Custom vars
        
    $maxAllowedSize 200000;
        
    $finalLocation "/home/flawclan/public_html/xxxx/projects/getimage/files/{$fileName}";
        
    //check  if file was uploaded
        
    try{
            if(
    is_uploaded_file($fileTempName)){
                
    //check extension
                
    if(($fileType != "image/gif") || ($fileSize $maxAllowedSize)){
                    throw new 
    Exception("Invalid file!");
                
    //move the file
                
    }else{
                    
    $moveFile move_uploaded_file($fileTempName,$finalLocation);
                    if(!
    $moveFile){
                        throw new 
    Exception("Could not move file!");
                    }else{
                        
    #echo "File sucessfully uploaded!";
                        #echo "<br />Normal upload: <img src=\"http://www.xxxx.com/test/files/{$fileName}\" />";
                    
    }
                }
            }else{
                echo 
    "Upload error: ".$fileError;
            }
        }catch (
    Exception $e){
            echo 
    $e->getMessage();
        }
        
    //try and open it, encode it
        
    $fh fopen($finalLocation,"r"); //rb = read  binary
        
    $binary fread($fh,$fileSize);
        
    fclose($fh);
        
    $encodedBinary chunk_split(base64_encode($binary));
        
        
    $ip $_SERVER['REMOTE_ADDR'];
                
        
    $sql"INSERT INTO `xxxx_images` (`id`,`image`,`posted_ip`) VALUES ('NULL','$encodedBinary','$ip')";
        
    $q mysql_query($sql);
        if(!
    $q){
            die(
    mysql_error());
        }else{
            echo 
    'File has been uploaded.';
        }
        
    unlink($finalLocation);
        
        
    }else{
        echo 
    "<form action=\"{$_SERVER['PHP_SELF']}\" method=\"post\" enctype=\"multipart/form-data\" >";
        echo 
    "File: <input type=\"file\" name=\"imageFile\" >";
        echo 
    "<br /><input type=\"submit\" name=\"upload\" value=\"Upload\" >";
        echo 
    "</form>";
    }
    ?>
    getImage.php
    PHP Code:
    <?php
    include_once("/home/flawclan/public_html/xxxx/class/startclasses.php");
    #############################################
    #getImage.php                               #
    #gets images from databases depending       #
    #on page and displays them                  #
    #############################################
    $imageId $_GET['id'];
    $errors = array("invalid" => "Invalid image tag!",
                    
    "notfound" => "Image not found!"); //error message array
    //check if vars are set
    if(!empty($imageId)){
        try{
            
    //check to make sure id is integer
            
    if(!is_numeric($imageId)){
                throw new 
    Exception($errors['invalid']);
            }
            
    //if so, setup sql and run query
            
    $sql "SELECT `id`,`image` FROM `xxxx_images` WHERE `id`='$imageId' LIMIT 1";
            
    $query mysql_query($sql);
            
    //check query failed
            
    if(!$query){
                throw new 
    Exception($errors['invalid']);
            
    //else check for rows
            
    }else{
                
    $num mysql_num_rows($query);
                if(
    $num == 0){
                    throw new 
    Exception($errors['notfound']);
                }elseif(
    $num == 1){
                    while(
    $row mysql_fetch_array($query)){
                        
    $showImage $row['image'];
                        if(empty(
    $showImage)){
                            
    $showImage "http://www.xxxx.com/ad/images/yourad.gif";
                            echo 
    $showImage;
                            die();
                        }else{
                            
    $showImage base64_decode($showImage);
                            echo 
    $showImage;
                            
                        }
                    }
                }else{
                    throw new 
    Exception($errors['invalid']);
                }
            }
        }catch(
    Exception $e){
            echo 
    $e->getMessage();
        }
    }else{
        
    header("Location: http://www.xxxx.com");
    }
    ?>
    view.php
    Code:
    <img src="getImage.php?id=2" />
    Any suggestions?

    Thanks
    -fl00d
    Last edited by fl00d; 05-19-2008 at 10:07 PM.

  • #2
    Senior Coder CFMaBiSmAd's Avatar
    Join Date
    Oct 2006
    Location
    Denver, Colorado USA
    Posts
    3,146
    Thanks
    2
    Thanked 333 Times in 325 Posts
    Unless you have a specific need to store an image in a database, don't. Store it as a file using the file system (that is what file systems are designed to do.)

    Database data is stored in a file. When you put an image or any other kind of file into a database, you are storing a file inside of another file. This just adds extra overhead processing to store the file, but more importantly, it adds extra overhead processing every time that file is output or displayed.

    Don't use base64 encoding, that adds an average of 33&#37; to the size of the data. It also adds even more extra overhead processing every time that file is output or displayed. If you do need to store an image in a database, use a BLOB data type.

    I don't see anywhere in your code where you are storing an image type header or outputting an image type header before the image data is output.

    If you browse directly to the url of the image - http://www.ridemtl.com/projects/geti...Image.php?id=5 you will get the raw image binary data. This data might or might not be intact, but because there is no image type header, it is not treated as an image by the browser.

    Edit: I looked at the tutorial link. The code is non-functional due to the missing image type header (plus the other problems I mentioned.)
    Last edited by CFMaBiSmAd; 05-19-2008 at 07:51 AM.
    If you are learning PHP, developing PHP code, or debugging PHP code, do yourself a favor and check your web server log for errors and/or turn on full PHP error reporting in php.ini or in a .htaccess file to get PHP to help you.

  • #3
    Regular Coder
    Join Date
    Mar 2007
    Location
    Quebec
    Posts
    261
    Thanks
    6
    Thanked 7 Times in 7 Posts
    You are correct, I haven't changed any headers to output an image. According to the tutorial I was following, it wasn't necessary (at least it didn't have it in the script).

    Here, this is an excerpt from the tutorial.
    But most of you are probably wondering why when you link to a page, you get an image. This is the reason: images arent defined by their 3 letter suffixes (such as jpg or gif), but by how their headers are written. IMAGE.PHP simply echos the image data, and acts like an image even though it just proccesses the request. This is why you get an image.
    That is written write after the code for view.php
    Code:
    <img src="getImage.php?id=2' />
    I'll try outputting with an image header now. On which page should it go though? getImage.php or view.php?
    Last edited by fl00d; 05-19-2008 at 07:58 AM.

  • #4
    bdl
    bdl is offline
    Regular Coder
    Join Date
    Apr 2007
    Location
    Camarillo, CA US
    Posts
    590
    Thanks
    4
    Thanked 83 Times in 82 Posts
    Some general comments
    • You don't store the image mime type or size, both what I consider to be essential on properly outputting the image. Related to this is the fact that you fail to use a header() call to set these values.
    • I've never seen the need to use base64 to encode the file prior to upload, unless you plan on using in some other method than simply calling from a script that outputs an image such as this.
    • You actually take the time to use move_uploaded_file() to move the file, then read that to upload, then use unlink to delete it. Just read the file stored in $_FILES['imageFile']['tmp_name'] - it's a 'real' file stored temporarily in the filesystem, usually under /tmp.
    • The function file_get_contents() is a simpler way to read the file in as a string.
    • Your SQL statement to store the image is storing the string 'NULL' in the `id` field instead of an actual NULL. I assume your `id` field is an auto_increment INT type field and this can use NULL, 0, or just plain leave the field out of the column list to set the auto_increment value.


    It looks as if CFMaBiSmAd covered many of these issues as I was typing..

  • #5
    Regular Coder
    Join Date
    Mar 2007
    Location
    Quebec
    Posts
    261
    Thanks
    6
    Thanked 7 Times in 7 Posts
    I put
    PHP Code:
    header("Content-Type: image/gif"); 
    on getImage.php before $showImage is echoed, and it gives the error The image http://www.ridemtl.com/projects/geti...Image.php?id=2 cannot be displayed because it contains errors.

    I've also removed base64 encoding/decoding. Even if my method isn't the most efficient (as pointed out ), I'd still like to try and get it working (I mean for storing images in database, I'll fix up the file moving and such so it's more efficient).

    Any more suggestions/ideas?

  • #6
    Senior Coder CFMaBiSmAd's Avatar
    Join Date
    Oct 2006
    Location
    Denver, Colorado USA
    Posts
    3,146
    Thanks
    2
    Thanked 333 Times in 325 Posts
    For your current problem of an invalid image even with the image header, the chunk_split() function is adding newlines that I am not sure that base64 decode removes.

    Another thing that comes to mind is text fields have an issue of either adding or truncating trailing white-space (I don't recall which.) This is why you need to use a BLOB data type IF you insist on storing binary data in a database (that is what BLOB data type is for.)

    The raw image data I saw contained a lot of white-space. I suspect that the basic concept used in that tutorial was never made functional.

    Edit: I'll also echo what bdl stated about the moving the uploaded file then opening and reading it. That is the worst way to do this, but fits with the rest of the problems with the tutorial.
    Last edited by CFMaBiSmAd; 05-19-2008 at 08:30 AM. Reason: fixed word
    If you are learning PHP, developing PHP code, or debugging PHP code, do yourself a favor and check your web server log for errors and/or turn on full PHP error reporting in php.ini or in a .htaccess file to get PHP to help you.

  • #7
    Regular Coder
    Join Date
    Mar 2007
    Location
    Quebec
    Posts
    261
    Thanks
    6
    Thanked 7 Times in 7 Posts
    Ah well, this is too problematic. I'll go with your original idea of using the file-system. Perhaps later on I'll take another shot at it using BLOB type fields instead.

    For now though, I remember reading a post saying their image script had been taken advantage of and a PHP file was uploaded instead of an image (PHP file tricked script by generating an image at same time?). How would I make sure that would not happen?
    I thought of perhaps using a .htaccess in the images folder that wouldn't parse PHP files, but I suppose if they were able to get a PHP file in instead of an image it wouldn't be that hard for them to copy the shell to another directory.


    ****EDIT****
    Wow... I got it working. I had forgotten that I had been using output buffering. I removed that (it was in the include file) and now everything seems to be working. Or at least the images show up.
    Last edited by fl00d; 05-19-2008 at 08:25 AM.


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •