mtdesigners's avatar

Image upload/delete without DB

Hi everyone, please bear with me on this one: I have a hero image on my laravel site and I want to be able to update that through front-end. I'm basically storing the image in Storage and deleting the previous one, by either overriding it or removing it. This works perfectly in development but the problems is in production(after deployment). The logic works but because the file name is the same and of the browsers' caching the image doesn't update as it should. Here's my Controller code:

public function storeHeroImage(Request $request) {
  if ($request->hasFile('image')) {
    Storage::disk('public')->delete('hero-images/hero.png'); // this is redundant as I am overriding the image
    $imgName = 'hero.png';
    $imgResize = Image::make($request->image->getRealPath());
    $imgResize = $imgResize->resize(1400, null, function ($constraint) {
        $constraint->aspectRatio();
    });
    $imgResize->save(storage_path() . '/app/public/hero-images/' . $imgName);
  }
  return back();
}

Here is the Blade:

<img class="w-full h-full"  src="{{ asset('storage/hero-images/hero.png') }}">

I tried to give a date string before the name so it can have a different name on upload, but I don't know how to call it in Blade template. I wanted something like the search function (i.e. *.png => any png file) I tried this:

<img class="w-full h-full"  src="{{ asset('storage/hero-images/' . Some Logic to allow any character before the rest of string .  '-hero.png') }}">

Is there a better way to achieve the same result?

PS: I have the exact some logic elsewhere except with the name getting changed and it works fine, but that goes through DB and I don't want this one to be that much work 🙂😅

Thank you all in advance for your patience and help

0 likes
2 replies
mtdesigners's avatar

Okay so after spending a day on this and wrecking my head, I went by using a DB:

public function storeHeroImage(Request $request) {
  if ($request->hasFile('image')) {
    // Delete the old photo
    $oldImg = DB::select('select * from hero_images ORDER BY id DESC LIMIT 1');
    Storage::disk('public')->delete('hero-images/' . $oldImg[0]->imgName);

    $imgName = time() . '-hero.png';
    $imgResize = Image::make($request->image->getRealPath());
    $imgResize = $imgResize->resize(1400, null, function ($constraint) {
         $constraint->aspectRatio();
    });

	// Insert into DB
    DB::insert('insert into hero_images (imgName) values (?)', [$imgName]);
    $imgResize->save(storage_path() . '/app/public/hero-images/' . $imgName);
  }
  return back();
}

and read i in my Blade component:

<img src="{{ asset('storage/hero-images/' . DB::select('select * from hero_images ORDER BY id DESC LIMIT 1')[0]->imgName) }}">

Of course if you were to use it make sure have the rights checks in place. Thank you 👨‍💻

Snapey's avatar
Snapey
Best Answer
Level 122

you can do it by applying an md5 hash of the file content but this would slow the page load a little.

<img class="w-full h-full"  
  src="{{ asset('storage/hero-images/hero.png') }}?{{md5('storage/hero-images/hero.png')}}">

if the image is swapped it produce a different signature

if the site is busy you could cache the signature

1 like

Please or to participate in this conversation.