0

I have a form on "add-category.php" that enables the admin to create a category and doing so includes uploading an image to a folder and inserts its file name and relevant text into the database. The script worked well with mysql_, but now it stopped working after I upgraded my "functions.php" to PDO. The issue is that the image cannot upload.

Warning: imagejpeg(/home/ script-directory/products/images/category/ec27a92192042fdc049e54477649fb30.jpg): failed to open stream: No such file or directory in /home/script-directory/includes/functions.php on line 385

This is my "add-category.php":

<?php

require_once '../../includes/config.php';

if(isset($_POST['txtName']))

{

    $categoryName = $_POST['txtName'];

    $categoryMtitle = $_POST['metaTitle'];

    $categoryMkey = $_POST['metaKey'];

    $categoryMdes = $_POST['metaDesc']; 

    $categoryDesc = $_POST['mtxDesc'];

    $imgName   = $_FILES['fleImage']['name'];

    $tmpName   = $_FILES['fleImage']['tmp_name'];

    // we need to rename the image name just to avoid

    // duplicate file names

    // first get the file extension

    $ext = strrchr($imgName, ".");

    // then create a new random name

    $newName = md5(rand() * time()) . $ext;

    // the category image will be saved here

    $imgPath = ALBUM_IMG_DIR . $newName;

    // resize all category image

    $result = createThumbnail($tmpName, $imgPath, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);

    if (!$result) {
        echo "Error uploading file";
        exit;

    }
    if(!$query = "INSERT INTO prod_cat (cat_name, cat_metatitle, cat_metakeywords, cat_metadescription, cat_description, cat_image, cat_date) 

              VALUES (:categoryName, :categoryMtitle, :categoryMkey, :categoryMdes, :categoryDesc, :newName, NOW())")
    {
        adminapologize("Error, adding product category failed.");         
    }

    $params = array(':categoryName' => $categoryName, ':categoryMtitle' => $categoryMtitle, ':categoryMkey' => $categoryMkey, ':categoryMdes' => $categoryMdes, ':categoryDesc' => $categoryDesc, ':newName' => $newName);

        var_dump($params);
        exit;

    // the category is saved, go to the category list 

    echo "<script>window.location.href='index.php?page=list-category';</script>";

    exit;

}

    // include add category template
    include("templates/add-category_template.php");

?>

Doing var_dump($params);
exit;
outputs this code:

array (size=6)
  ':categoryName' => string 'Balls' (length=5)
  ':categoryMtitle' => string 'Corporate Gift balls' (length=20)
  ':categoryMkey' => string 'ball, balls' (length=11)
  ':categoryMdes' => string 'Buy corporate gift items like balls' (length=35)
  ':categoryDesc' => string '<p>Buy corporate gift items like balls</p>' (length=42)
  ':newName' => string 'f59723c81fe0c4235b57ad338e981bff.jpg' (length=36)

Here is the definition of image location in "config.php":

 // APP_ROOT will always be set to 2 directorys up from the location of this file
    define('APP_ROOT', dirname(dirname(__FILE__)) . '/');
    // a category can have an image used as thumbnail
    // we save the category image here
    define('ALBUM_IMG_DIR', APP_ROOT . 'products/images/category/');
// all images inside an category are stored here
define('GALLERY_IMG_DIR', APP_ROOT . 'products/images/gallery/');



 In the "functions.php", I have this code regarding PDO and image upload:
     /**

    * Executes SQL statement, possibly with parameters, returning

    * a pdo statement object on success, handling and halting execution on error.

    */

    function query($sql, $parameters = null)

    {

        static $pdo; // define the var as static so that it will persist between function calls



    try

    {

        // if no db connection, make one

        if (!isset($pdo))

        {

            // connect to database



            // you should set the character encoding for the connection



            $pdo = new PDO("mysql:dbname=" . DB_NAME . ";host=" . DB_SERVER, DB_USERNAME, DB_PASSWORD);

            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the error mode to exceptions

            $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES,false); // turn emulated prepares off

            $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE,PDO::FETCH_ASSOC); // set default fetch mode to assoc so that you don't have to explicitly list the fetch mode every place

        }



        if(empty($parameters)){

            // no bound inputs

            $stmt = $pdo->query($sql);

        } else {

            // has bound inputs

            $stmt = $pdo->prepare($sql);



             // you should use explicit bindValue() statements to bind any inputs, instead of supplying them as a parameter to the ->execute() method. the comments posted in your thread lists the reasons why.



            $stmt->execute($parameters);

        }



        }

        catch (Exception $e)

        {

            // all errors with the connection, query, prepare, and execute will be handled here



            // you should also use the line, file, and backtrace information to produce a detailed error message

            // if the error is due to a query, you should also include the $sql statement as part of the error message

            // if $pdo ($handle in your code) is set, it means that the connection was successful and the error is due to a query. you can use this to include the $sql in the error message.



            trigger_error($e->getMessage(), E_USER_ERROR);

            //exit; // note: E_USER_ERROR causes an exit, so you don't need an exit; here.

        }



            return $stmt; // if the query ran without any errors, return the pdo statement object to the calling code

        }



/*

    Upload an image and create the thumbnail. The thumbnail is stored 

    under the thumbnail sub-directory of $uploadDir.



    Return the uploaded image name and the thumbnail also.

*/

function uploadImage($inputName, $uploadDir)

{

    $image     = $_FILES[$inputName];

    $imagePath = '';

    $thumbnailPath = '';



    // if a file is given

    if (trim($image['tmp_name']) != '') {

        $ext = substr(strrchr($image['name'], "."), 1); 



        // generate a random new file name to avoid name conflict

        // then save the image under the new file name

        $imagePath = md5(rand() * time()) . ".$ext";

        $result    = move_uploaded_file($image['tmp_name'], $uploadDir . $imagePath);



        if ($result) {

            // create thumbnail

            $thumbnailPath =  md5(rand() * time()) . ".$ext";

            $result = createThumbnail($uploadDir . $imagePath, $uploadDir . 'thumbnail/' . $thumbnailPath, THUMBNAIL_WIDTH);



            // create thumbnail failed, delete the image

            if (!$result) {

                unlink($uploadDir . $imagePath);

                $imagePath = $thumbnailPath = '';

            } else {

                $thumbnailPath = $result;

            }   

        } else {

            // the image cannot be uploaded

            $imagePath = $thumbnailPath = '';

        }



    }





    return array('image' => $imagePath, 'thumbnail' => $thumbnailPath);

}



/*

    Create a thumbnail of $srcFile and save it to $destFile.

    The thumbnail will be $width pixels.

*/

function createThumbnail($srcFile, $destFile, $width, $quality = 75)

{

    $thumbnail = '';



    if (file_exists($srcFile)  && isset($destFile))

    {

        $size        = getimagesize($srcFile);

        $w           = number_format($width, 0, ',', '');

        $h           = number_format(($size[1] / $size[0]) * $width, 0, ',', '');



        $thumbnail =  copyImage($srcFile, $destFile, $w, $h, $quality);

    }



    // return the thumbnail file name on sucess or blank on fail

    return basename($thumbnail);

}



/*

    Copy an image to a destination file. The destination

    image size will be $w X $h pixels

*/

function copyImage($srcFile, $destFile, $w, $h, $quality = 75)

{

    $tmpSrc     = pathinfo(strtolower($srcFile));

    $tmpDest    = pathinfo(strtolower($destFile));

    $size       = getimagesize($srcFile);



    if ($tmpDest['extension'] == "gif" || $tmpDest['extension'] == "jpg")

    {

       $destFile  = substr_replace($destFile, 'jpg', -3);

       $dest      = imagecreatetruecolor($w, $h);

       //imageantialias($dest, TRUE);

    } elseif ($tmpDest['extension'] == "png") {

       $dest = imagecreatetruecolor($w, $h);

       //imageantialias($dest, TRUE);

    } else {

      return false;

    }



    switch($size[2])

    {

       case 1:       //GIF

           $src = imagecreatefromgif($srcFile);

           break;

       case 2:       //JPEG

           $src = imagecreatefromjpeg($srcFile);

           break;

       case 3:       //PNG

           $src = imagecreatefrompng($srcFile);

           break;

       default:

           return false;

           break;

    }



    imagecopyresampled($dest, $src, 0, 0, 0, 0, $w, $h, $size[0], $size[1]);



    switch($size[2])

    {

       case 1:

       case 2:

           imagejpeg($dest,$destFile, $quality);

           break;

       case 3:

           imagepng($dest,$destFile);

    }

    return $destFile;



}

Your help would be much appreciated. Thanks in advance.

2
Contributors
13
Replies
70
Views
1 Year
Discussion Span
Last Post by mexabet
Featured Replies
  • 1
    diafol 3,720   1 Year Ago

    The PDO way would be something like this: $stmt = $db->prepare($sql); $stmt->execute($params); The fetch method is up to you, e.g. $data = $stmt->fetchAll(); Read More

0

I can't see where you're running a query (or prepared statement). You have a SQL string, but nothing else.

0

The mysql query I originally had on add-category.php was this:

$query = "INSERT INTO prod_cat (cat_name, cat_metatitle, cat_metakeywords, cat_metadescription, cat_description, cat_image, cat_date) 
        VALUES ('$categoryName', '$categoryMtitle', '$categoryMkey', '$categoryMdes', '$categoryDesc', '$newName', NOW())";
mysql_query($query) or die('Error, add product category failed : ' . mysql_error());

Please, bear with me; I'm still struggling to get a handle on PDO prepared statement and this was my attempt at converting the above code:

if(!$query = "INSERT INTO prod_cat (cat_name, cat_metatitle, cat_metakeywords, cat_metadescription, cat_description, cat_image, cat_date) 
    VALUES (:categoryName, :categoryMtitle, :categoryMkey, :categoryMdes, :categoryDesc, :newName, NOW())")
{
    adminapologize("Error, adding product category failed.");         
}

$params = array(':categoryName' => $categoryName, ':categoryMtitle' => $categoryMtitle, ':categoryMkey' => $categoryMkey, ':categoryMdes' => $categoryMdes, ':categoryDesc' => $categoryDesc, ':newName' => $newName);

Can you please help?

1

The PDO way would be something like this:

$stmt = $db->prepare($sql);
$stmt->execute($params);

The fetch method is up to you, e.g.

$data = $stmt->fetchAll();
0

@cereal, Thanks for the insight.

I updated the select query on add-category.php to this:

$query = "INSERT INTO admin (username, hash, email, phone) VALUES (:username, :hash, :email, :phone)";
$params = array(':username' => $username, 'hash' => $hash, ':email' => $email, ':phone' => $phone);

$result = query($query, $params);
$affected_rows = $result->rowCount();

Now all the data are inserted into the database, but the image upload and move to upload directory still fails. Any idea?

Edited by mexabet

0

I'm assuming that the failure is due to the original image manipulation routine.

There are a few "iffy" lines here.

Getting the extension and other bits of filename info should be left to pathinfo(). For example...

$fileinfo = pathinfo($_FILES[$inputName]['tmp_name']); 

$fileinfo['basename'] will give the full filename (name + extension)
$fileinfo['extension'] will give the extension
$fileinfo['filename'] will give the filename without the extension

Check for errors with $_FILES[$inputName]['error'] (should be = 0)

There are a few more but it looks as you are passing a file(name) to the imagejpeg() function, but it requires an image resource. The second optional parameter for this function takes a (storage) filename. Use this if you want to store a physical file, otherwise you will create and possibly output the image stream.

0

@diafol, thanks for your contribution.

Which file do you suggest I edit and which line? add-category.php or functions.php or config.php? Sorry, I'm just a learner.

0

The issue is with what you're passing to imagejpeg(). Sorry done for today. Back tomorrow. Anybody else in the meantime?

0

I still don't get it. can you please tell me the exact file to edit and which line and a replacement code. Thanks in advance.

0

Warning: imagejpeg(/home/ script-directory/products/images/category/ec27a92192042fdc049e54477649fb30.jpg): failed to open stream: No such file or directory in /home/script-directory/includes/functions.php on line 385

Can you confirm line 385?

0

Line 385 has this code:

imagejpeg($dest,$destFile, $quality);
0

The directory, category, exists in script-directory/products/images/category.

0

Sorry mexabet, but those image function were doing my head in! :) So here's a simple class, that hopefully will be easier to use and debug.:

<?php
/**
 * Class UpThumb
 */
class UpThumb
{
    private $valid = false;
    private $getSize;
    private $newFilename;
    private $newThumbPath;
    private $newPath;
    private $file;
    private $allowedExt = ['gif', 'jpeg', 'jpg', 'png'];
    private $allowedExif = [1, 2, 3];
    private $ext;

    /**
     * @param $inputName
     * @param $uploadDir
     * @return $this|bool
     */
    public function uploadImage($inputName, $uploadDir)
    {
        //No error checking included - see http://php.net/manual/en/features.file-upload.php for info
        if (isset($_FILES[$inputName]) && $_FILES[$inputName]['error'] == 0) {
            $this->file = $_FILES[$inputName];
            $pathInfo = pathinfo($this->file['name']);
            $this->ext = strtolower($pathInfo['extension']);
            if ($this->checkAllowed($this->ext) && in_array(exif_imagetype($this->file['tmp_name']),$this->allowedExif)) {
                $this->getSize = getimagesize($this->file['tmp_name']);
                $this->newFilename = md5(rand() * time()) . "." . $this->ext;
                $this->newPath = $uploadDir . $this->newFilename;
                if (move_uploaded_file($this->file['tmp_name'], $this->newPath)) {
                    $this->valid = true;
                    return $this;
                }
            }
        }
        return false;
    }

    /**
     * @return array
     */
    public function getFilenames()
    {
        $ret = [];
        $ret['upload'] = $this->newPath;
        if($this->newThumbPath) $ret['thumb'] = $this->newThumbPath;
        return $ret;
    }

    /**
     * @param $thumbPathPrefix
     * @param null|int $w thumbnail width
     * @param null|int $h thumbnail height px
     * @param string $type gif|jpeg|jpg|png
     * @param int $quality 0-9 for png|0-100 for jpeg
     * @return $this
     */
    public function createThumb($thumbPathPrefix, $w = 100, $h = NULL, $type = 'jpg', $quality = 75)
    {
        $type = strtolower($type);
        $this->newThumbPath = $thumbPathPrefix . $this->newFilename;
        if($this->valid && (is_int($w) || is_int($h)) && $this->checkAllowed($type)) {

            list($tW, $tH) = $this->calcDimensions($w, $h);
            $thumbRes = imagecreatetruecolor($tW, $tH);

            switch($this->ext) {
                case 'gif':
                    $imgRes = imagecreatefromgif($this->newPath);
                    break;
                case 'jpeg':
                case 'jpg':
                    $imgRes = imagecreatefromjpeg($this->newPath);
                    break;
                case 'png':
                    $imgRes = imagecreatefrompng($this->newPath);
                    break;
            }

            imagecopyresampled($thumbRes, $imgRes, 0, 0, 0, 0, $tW, $tH, $this->getSize[0], $this->getSize[1]);

            switch($type) {
                case 'gif':
                    imagegif($thumbRes, $this->newThumbPath);
                    break;
                case 'jpeg':
                case 'jpg':
                    $quality = $this->checkQuality($quality, 0, 100);
                    imagejpeg($thumbRes, $this->newThumbPath, $quality);
                    break;
                case 'png':
                    $quality = $this->checkQuality($quality, 0, 9);
                    imagepng($thumbRes, $this->newThumbPath, $quality);
                    break;
            }
            return $this;
        }
    }

    /**
     * @param $type
     * @return bool
     */
    private function checkAllowed($type)
    {
        return in_array($type, $this->allowedExt);
    }


    /**
     * @param $w
     * @param $h
     * @return array
     */
    private function calcDimensions($w, $h)
    {
        if(is_int($w) && is_int($h)) return [$w, $h];
        if(is_int($w)) return [$w, $this->getSize[1] * $w / $this->getSize[0]];
        return [$this->getSize[0] * $h / $this->getSize[1], $h];
    }

    /**
     * @param $quality
     * @param $min
     * @param $max
     * @return null|int
     */
    private function checkQuality($quality, $min, $max)
    {
        if(!is_int($quality)){
            return NULL;
        } elseif($quality > $max) {
            return $max;
        } elseif($quality < $min) {
            return $min;
        } else {
            return $quality;
        }
    }
}


//Create Object
//Upload, Create Thumb and get Filenames
if(isset($_FILES['myfile'])) {
    $x = new UpThumb;
    $p = $x->uploadImage('myfile', 'upload/')->createThumb('thumbs/')->getFilenames();
}

?>


<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
</head>
<body>

<?php
    if(isset($p['upload'])) echo "UPLOADED:<br /> <img src = '{$p['upload']}' /> <p>{$p['upload']}</p>";
    if(isset($p['thumb'])) echo "THUMB:<br /> <img src = '{$p['thumb']}' /> <p>{$p['thumb']}</p>";
?>

  <form method="post" enctype="multipart/form-data">
      <input type="file" name="myfile" />
      <input type="submit" value="Go" />
  </form>

</body>
</html>

Works for me.

0

Thanks, I'll try it and see if I can integrate it successfully into my script.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.