imagecache icon indicating copy to clipboard operation
imagecache copied to clipboard

images not showing on laravel 5.4

Open BartHuis opened this issue 7 years ago • 37 comments

Hi, Just installed intervention/image and intervention/imagecache on laravel 5.4 I couldn't get the package working right. Tracked down the way how the image should be displayed all down to the ImageCacheController. Requesting the original route The current output it returns is:

<html><head><meta name="viewport" content="width=device-width, minimum-scale=0.1"></head><body style="margin: 0px; background: rgb(14, 14, 14);"><img style="-webkit-user-select: none;background-position: 0px 0px, 10px 10px;background-size: 20px 20px;background-color: white;background-image:linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee 100%),linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee 100%);" src="http://domain.ext/img/original/image.jpg"></body></html>

and it's not showing any picture, only a square on a black screen: squareinblack.png

when i change the getOriginal function to:

/**
     * Get HTTP response of original image file
     *
     * @param  string $filename
     * @return Illuminate\Http\Response
     */
    public function getOriginal($filename)
    {
        $path = $this->getImagePath($filename);

        //return $this->buildResponse();
    
        $imageData = base64_encode(file_get_contents($path));

        // Format the image SRC:  data:{mime};base64,{data};
        $src = 'data: '.mime_content_type($path).';base64,'.$imageData;

        // Echo out a sample image
        return '<img src="' . $src . '">';
    }

and requesting the original route, the output is:

<html><head></head><body><img src="data: image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQICAQECAQEBAgICAgICAgICA............etc................."></body></html>

and it's just working

I think something is wrong with the buildResponse function?

requesting other pre defined templates like small, medium and large are giving the same square as result.

Bart

BartHuis avatar Mar 28 '17 14:03 BartHuis

Hi,

I have the same issue on Laravel 5.1.31 and PHP 5.5.38.

Bart, have you fixed it?

Thanks.

ghost avatar Apr 04 '17 10:04 ghost

try this for instance (different for your example but.....) spent last 2 hours trying to find a fix and this did it!

ob_end_clean();
return($cachedImage->response('jpg'));
```php

from: 
http://simpledeveloper.com/how-to-fix-laravel-response-image-download-in-laravel/
https://laravel.io/forum/02-16-2016-laravel-51-intervention-corrupted-image

codemonkeynorth avatar Apr 05 '17 02:04 codemonkeynorth

maybe @olivervogel can look at this, because it seems to be a package problem and not a usage problem?

BartHuis avatar Apr 05 '17 07:04 BartHuis

thnx @codemonkeynorth seems to work when i add ob_end_clean(); at 2 places, so @zaplachinsky and people at issue #60 try to change the ImageCacheController.php to this: (of cource this is not THE solution, would be nice if @olivervogel will still look into the real problem)

<?php

namespace Intervention\Image;

use Closure;
use Intervention\Image\ImageManager;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Http\Response as IlluminateResponse;
use Config;

class ImageCacheController extends BaseController
{
    /**
     * Get HTTP response of either original image file or
     * template applied file.
     *
     * @param  string $template
     * @param  string $filename
     * @return Illuminate\Http\Response
     */
    public function getResponse($template, $filename)
    {
        switch (strtolower($template)) {
            case 'original':
                return $this->getOriginal($filename);

            case 'download':
                return $this->getDownload($filename);
            
            default:
                return $this->getImage($template, $filename);
        }
    }

    /**
     * Get HTTP response of template applied image file
     *
     * @param  string $template
     * @param  string $filename
     * @return Illuminate\Http\Response
     */
    public function getImage($template, $filename)
    {
        $template = $this->getTemplate($template);
        $path = $this->getImagePath($filename);

        // image manipulation based on callback
        $manager = new ImageManager(Config::get('image'));
        $content = $manager->cache(function ($image) use ($template, $path) {

            if ($template instanceof Closure) {
                // build from closure callback template
                $template($image->make($path));
            } else {
                // build from filter template
                $image->make($path)->filter($template);
            }
            
        }, config('imagecache.lifetime'));
    
        ob_end_clean();
        return $this->buildResponse($content);
    }

    /**
     * Get HTTP response of original image file
     *
     * @param  string $filename
     * @return Illuminate\Http\Response
     */
    public function getOriginal($filename)
    {
        $path = $this->getImagePath($filename);
        ob_end_clean();
        return $this->buildResponse(file_get_contents($path));
    }

    /**
     * Get HTTP response of original image as download
     *
     * @param  string $filename
     * @return Illuminate\Http\Response
     */
    public function getDownload($filename)
    {
        $response = $this->getOriginal($filename);

        return $response->header(
            'Content-Disposition',
            'attachment; filename=' . $filename
        );
    }

    /**
     * Returns corresponding template object from given template name
     *
     * @param  string $template
     * @return mixed
     */
    private function getTemplate($template)
    {
        $template = config("imagecache.templates.{$template}");

        switch (true) {
            // closure template found
            case is_callable($template):
                return $template;

            // filter template found
            case class_exists($template):
                return new $template;
            
            default:
                // template not found
                abort(404);
                break;
        }
    }

    /**
     * Returns full image path from given filename
     *
     * @param  string $filename
     * @return string
     */
    private function getImagePath($filename)
    {
        // find file
        foreach (config('imagecache.paths') as $path) {
            // don't allow '..' in filenames
            $image_path = $path.'/'.str_replace('..', '', $filename);
            if (file_exists($image_path) && is_file($image_path)) {
                // file found
                return $image_path;
            }
        }

        // file not found
        abort(404);
    }

    /**
     * Builds HTTP response from given image data
     *
     * @param  string $content 
     * @return Illuminate\Http\Response
     */
    private function buildResponse($content)
    {
        // define mime type
        $mime = finfo_buffer(finfo_open(FILEINFO_MIME_TYPE), $content);

        // return http response
        return new IlluminateResponse($content, 200, array(
            'Content-Type' => $mime,
            'Cache-Control' => 'max-age='.(config('imagecache.lifetime')*60).', public',
            'Etag' => md5($content)
        ));
    }
}

BartHuis avatar Apr 05 '17 12:04 BartHuis

What is the actual output on the requested image route? (Broken image or square on a black screen could be anything.)

olivervogel avatar Apr 05 '17 13:04 olivervogel

@olivervogel thanks for the quick folowup ;)

<html><head><meta name="viewport" content="width=device-width, minimum-scale=0.1"></head><body style="margin: 0px; background: rgb(14, 14, 14);"><img style="-webkit-user-select: none;background-position: 0px 0px, 10px 10px;background-size: 20px 20px;background-color: white;background-image:linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee 100%),linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, #eee 75%, #eee 100%);" src="http://domain.ext/img/original/image.jpg"></body></html>

BartHuis avatar Apr 05 '17 13:04 BartHuis

No, I mean what do you get if you request only the image?

http://domain.ext/img/original/image.jpg

olivervogel avatar Apr 05 '17 13:04 olivervogel

here i can also see the one string is working, the other not: http://freeonlinetools24.com/base64-image

BartHuis avatar Apr 05 '17 13:04 BartHuis

@olivervogel when you're saved the base64 codes, please tell me, i'll delete it then, just to prevent others from tracking things we do ;)

BartHuis avatar Apr 05 '17 13:04 BartHuis

Why do you get base64 encoded data from the route? If you setup URL based image manipulation you should just get regular image data.

PS: You can delete.

olivervogel avatar Apr 05 '17 13:04 olivervogel

deleted

BartHuis avatar Apr 05 '17 13:04 BartHuis

no, i just get the image, but if i click the source in chrome, i get the base64, what other response would you like me to post? ;)

BartHuis avatar Apr 05 '17 13:04 BartHuis

@olivervogel if you would like to, you can look with me at teamviewer? cant realy post all real routes and everything becouse of bussiness use ;)

BartHuis avatar Apr 05 '17 13:04 BartHuis

@olivervogel, I always get this square image when I request something like this:

http://domain.ext/img/original/image.jpg

fireshot capture 156 - - http___dev mousegame ru_i_original_uploads_2016_12_07_a364c7135214d277f

ghost avatar Apr 05 '17 13:04 ghost

@zaplachinsky that's the same problem here ;)

BartHuis avatar Apr 05 '17 13:04 BartHuis

I think you setup imagecache like it is described in the docs. I would just like to know what image data you get from the route, when you got a corrupt image (square on black screen).

Just do a quick curl and take a look what you get:

$ curl -r 0-99 http://domain.ext/img/original/image.jpg

olivervogel avatar Apr 05 '17 13:04 olivervogel

when its in the working and not working modus, i both get a screen with code but after a milisecond it clears and gives me:

          ▒@1▒▒▒

Bart@machine location
$ 1;2c^C

BartHuis avatar Apr 05 '17 13:04 BartHuis

so nothing to see here

BartHuis avatar Apr 05 '17 13:04 BartHuis

so chrome is just showing the right image when ob end clean in added, and the little square when not added. only when going into the chrome inspector and clicking on the sources tab, and clicking the image, is giving the base64 data, the working one and the not working one. any other inspector tab you want me to look at and copy paste to you? or wanna look with me?

BartHuis avatar Apr 05 '17 13:04 BartHuis

@olivervogel and yes "I think you setup imagecache like it is described in the docs." yes i did it just folowing the docs ;)

BartHuis avatar Apr 05 '17 14:04 BartHuis

does this show anything useful?.. without, and then with ob_end_clean();

note the whitespace at the beginning

without img-no-obclean

with img-with-obclean

codemonkeynorth avatar Apr 05 '17 19:04 codemonkeynorth

@codemonkeynorth yes, the base64 version that @olivervogel has now, was also different

BartHuis avatar Apr 06 '17 07:04 BartHuis

my working and not working give different base64, but the same response as you, but instead of spaces in the beginning, i get a blank line at the wrong file, and no blank line at the right file.


ÿØÿàJFIF``ÿþ;CREATOR: gd-jpeg v1.0 (using IJG JPEG v80), quality = 90
ÿÛC



BartHuis avatar Apr 06 '17 07:04 BartHuis

@codemonkeynorth what cache meganism is your default? here it's redis. config/cache.php:

    'default' => env('CACHE_DRIVER', 'file'),

.env:

CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_DRIVER=redis

.env overrides the config

but, also when changing to CACHE_DRIVER=file, php restart, clear cache, it has the same behaviour.

what cache do you use @olivervogel ?

BartHuis avatar Apr 06 '17 07:04 BartHuis

I'm using file cache.

codemonkeynorth avatar Apr 06 '17 07:04 codemonkeynorth

The whitespace is the problem. But neither Intervention Image or Intervention Imagecache produces this whitespace. I think this may be a issue with Laravel's or Symfony's Cache/HTTP modules or the combination of them.

This might be helpful: http://simpledeveloper.com/how-to-fix-laravel-response-image-download-in-laravel/

olivervogel avatar Apr 06 '17 08:04 olivervogel

@olivervogel that's the same we do now, adding the ob_end_clean() before the return... so is that realy the solution? and should be added to your package? where is the output buffer start then? as i read the topic, it is somewhere in laravel itself, but the laravel code dousn't close it?

BartHuis avatar Apr 06 '17 08:04 BartHuis

hi @olivervogel . that's the link I posted above, which is where i got ob_end_clean() from

so I understand that it's a general Laravel buffer issue not a specific Intervention issue ,

thanks.

codemonkeynorth avatar Apr 06 '17 08:04 codemonkeynorth

Adding ob_end_clean to Intervention Imagecache seems like a fix/hack for a bug in another package. I think the problem should be fixed properly, where it is caused.

olivervogel avatar Apr 06 '17 08:04 olivervogel

@olivervogel i'll ask laravel and point them to this ;)

BartHuis avatar Apr 06 '17 08:04 BartHuis