• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

getimagesize and XenForo_Image_Abstract::createFromFile failing

chrisj

Active member
#1
I followed Jaxel's code from 2010: http://xenforo.com/community/threads/how-does-the-image-parser-work.7783/

This is run as part of a cron and the page returns blank. I tried turning on php error reporting but it doesn't make a difference. I decided to log everything in a file and I was able to track the problem to getimagesize and XenForo_Image_Abstract::createFromFile. It seems it either one can fail.

All the url's I pass are always valid image urls. They are also all png format.

Here is the code I am using.

PHP:
protected function saveThumbnail($imageUrl, $type, $id, $width){
        XenForo_Helper_File::log(
            'psnleaderboard-test',
            sprintf("saveThumbnail - %s\n%s\t%s\t%s\n",
            $imageUrl, $type, $id, $width)
        );
     
        echo "<br/>saveThumbnail($imageUrl, $type, $id, $width)<br/>";
     
        // get extension of image
            $extension = XenForo_Helper_File::getFileExtension($imageUrl);
         
            XenForo_Helper_File::log(
                'psnleaderboard-test',
                sprintf("got extension: %s\n", $extension)
            );
 
            // get width, height and type of image
            $imageInfo = @getimagesize($imageUrl); // This sometimes fails
            if (!$imageInfo)
            {
                XenForo_Helper_File::log(
                    'psnleaderboard-test',
                    sprintf("image info failed\n")
                );
                echo "image info failed<br/>";
                return false;
            }
         
            XenForo_Helper_File::log(
                'psnleaderboard-test',
                sprintf("imageInfo[2] - %s\n", $imageInfo[2])
            );
 
            // set target save location
            $filePath = XenForo_Helper_File::getExternalDataPath().'/psnleaderboards/images/'.$type.'/s/'.$id.'.'.$extension;
         
            XenForo_Helper_File::log(
                'psnleaderboard-test',
                sprintf("filepath created\n")
            );
 
            // create image object from existing image
            if ($image = XenForo_Image_Abstract::createFromFile($imageUrl, $imageInfo[2])) // this also can fail
            {
                XenForo_Helper_File::log(
                    'psnleaderboard-test',
                    sprintf("image created\n")
                );
             
                // resize image object to 160 width
                $image->thumbnail($width);
                print_r($imageInfo);
 
                // save thumbnail image to target location
                $directory = dirname($filePath);
                if (XenForo_Helper_File::createDirectory($directory, true) && is_writable($directory))
                {
                    if (file_exists($filePath))
                    {
                        unlink($filePath);
                    }
             
                    $image->output($imageInfo[2], $filePath);
                 
                    XenForo_Helper_File::log(
                        'psnleaderboard-test',
                        sprintf("succeeded saving Thumbnail\n")
                    );
                 
                    return true;
                }
            }
            XenForo_Helper_File::log(
                'psnleaderboard-test',
                sprintf("failed saving Thumbnail\n")
            );
        return false;
    }
 

Naatan

Well-known member
#4
Yes, this is running on MAMP and also it works the majority of the time.
Neither the fact that it runs on MAMP nor that it works "most of the time" answers the question of "whether your webserver has permission to read the image file" though.

Run is_readable on your file and see what it says.
 

chrisj

Active member
#5
By image file, do you mean image on the remote website? I tried is_readable on the url and that fails every time. If you are talking about the image file I am trying to create, I don't see how I can try and read what hasn't been created. I do check to see if I have write permission.
 

Naatan

Well-known member
#6
By image file, do you mean image on the remote website? I tried is_readable on the url and that fails every time. If you are talking about the image file I am trying to create, I don't see how I can try and read what hasn't been created. I do check to see if I have write permission.

There's your problem, you're passing in a remote image (presumably a http address), although this can work with getimagesize, it does not work with XenForo's image library. Furthermore it is bad practice to do this even if it would work, as you have no control what so ever over it's method of retrieval and are limited in exception handling.

The better way of doing this is to first download the image (with cUrl or otherwise) and then perform your image manipulations on your local file. Afterwards you just delete whatever files you don't need anymore. Save downloaded images to
sys_get_temp_dir() to ensure files will always get cleaned up even if your script failed (unless you don't want them deleted of course).
 

chrisj

Active member
#7
Thank you, it seems to be working perfectly now. For those curious, this is the working code:
PHP:
/*
Creates a local image for a url and compresses it
 
@param string imageUrl, string type, string id, string width
 
@return true if image is successfully created
*/
protected function saveThumbnail($imageUrl, $type, $id, $width){
 
        // create file with random name in system temp dir
        $temp_file = tempnam(sys_get_temp_dir(), 'Psi');
        $fp = fopen($temp_file, 'w');
 
        // write image to file
        $ch = curl_init($imageUrl);
        curl_setopt($ch, CURLOPT_FILE, $fp);
        $data = curl_exec($ch);
 
        curl_close($ch);
        fclose($fp);
 
 
        if ($temp_file && !is_readable($temp_file))
        {
            throw new XenForo_Exception('The temporary file for the image can not be read.');
        }
 
 
            // get extension of image
            $extension = XenForo_Helper_File::getFileExtension($imageUrl);
 
            // get width, height and type of image
            $imageInfo = @getimagesize($temp_file);
            if (!$imageInfo)
            {
                return false;
            }
 
            // set target save location
            $filePath = XenForo_Helper_File::getExternalDataPath().'/psnleaderboards/images/'.$type.'/s/'.$id.'.'.$extension;
 
            // create image object from existing image
            if ($image = XenForo_Image_Abstract::createFromFile($temp_file, $imageInfo[2]))
            {
                // delete temporary file
                if (file_exists($temp_file))
                {
                    unlink($temp_file);
                }
       
                // resize image object to 160 width
                $image->thumbnail($width);
                print_r($imageInfo);
 
                // save thumbnail image to target location
                $directory = dirname($filePath);
                if (XenForo_Helper_File::createDirectory($directory, true) && is_writable($directory))
                {
                    if (file_exists($filePath))
                    {
                        unlink($filePath);
                    }
       
                    $image->output($imageInfo[2], $filePath);
 
                    return true;
                }
            }
 
        return false;
    }