Search code examples
phplaravelcachingintervention

Image manipulation not updated in cache


On a page where users can rotate their uploaded picture, there is a button to rotate the picture. This is done using Intervention image, but the same result (and problem) has been achieved using PHP.

The problem is that the image rotation works, but the rotated image is not shown in the browser. This is probably due to cache, because when manually emptying the cache, the rotated picture is indeed shown in the browser.

public function rotate($picture_id) {

    // get picture location
    $path = Picture::where('id',$picture_id)->first()->location;

    // Rotate the picture
    $path_orig = storage_path('app/public/'.$path);
    $img_orig = Image::make($path_orig)
                ->rotate(-90)
                ->save($path_orig);

    // Rotate thumbnails etc
    ...

    return Redirect::back();
}

SOLUTION Update the filename with a random string.

public function rotate($picture_id) {

    // get picture location
    $path = Picture::where('id',$picture_id)->first()->location;

    // Path to picture
    $path_orig = storage_path('app/public/'.$path);
    $path_s = public_path($path);

    // New path
    do {
        $newKey = str_random(40);
        $ext = File::extension($path_orig);
        $dir = dirname($path_orig);
        $path_L_new = $dir.'/'.$newKey.'.'.$ext;
        $path_S_new = public_path('folder/'.$newKey.'.'.$ext);
    }
    while ( count(Picture::where('location',$path_L_new)->get()) > 0 );

    // Rotate images
    $img_L_new = Image::make($path_orig)
                ->rotate(-90)
                ->save($path_L_new);

    $img_S_new = Image::make($path_s)
                ->rotate(-90)
                ->save($path_S_new);

    // Delete old files
    Storage::delete($path);
    File::delete(public_path($path));

    // Update location
    $pic = Picture::where('id',$picture_id)->first()->update(array('location' => 'folder/'.$newKey.'.'.$ext));

    // Show new picture
    return Redirect::back();

}

Solution

  • You have to append a random or unique string at the of the image src:

    <img src="/path/to/file.jpg{{ time() }}">
    

    But be careful that don't append new random string to the end of the image src when the image is not being updated. If you do, the image won't be cached.

    Proper way: When an image updated, it's better to store a random string for this image and store it in database. And when displaying the images, append peer random string to it. Don't generate new random string on every call.