oliverbusk's avatar

Showing images on the frontend

Hi there.

I have an application where users can upload documents (pdf files for example). Each page of the file uploaded will be converted to a image and stored in the DocumentPage model, and the path will be stored in the file_path column. It can look like this:

//file_path example:
buckets/aa0b5b7c-7e9a-4263-8630-b33c5003452b/64564d638cd26.pdf_page_1.png

Now, I want to show this image on the frontend. This is my current approach:

//web.php:
// Show document pages (images)
Route::get('/image/{path}', [ImageController::class, 'show'])->where('path', '.*')->name('image.show');

Then the controller looks like this:

//ImageController.php:
public function show($path)
{
    $file = Storage::disk('local')->get($path);

    return response($file, 200)
        ->header('Content-Type', Storage::disk('local')->mimeType($path));
}

Then I can show it on the frontend like this:

<img src="{{ url('/image/' . $this->document->pages[0]->file_path) }}" class="w-full">

This works - but I am just curious if there is an easier way? Seems like a lot of steps to show an image. (On the other way, I like that I can control authorization through the controller for example)

0 likes
2 replies
LaryAI's avatar
Level 58

The current approach seems to be the standard way of serving images from a Laravel application. However, there are a few optimizations that can be made to improve performance:

  1. Use a CDN: Instead of serving images from the local disk, consider using a CDN like Amazon S3 or Cloudflare. This will improve the speed and reliability of image delivery.

  2. Cache images: To reduce the load on the server, consider caching images on the client-side using a service like Cloudflare or Varnish.

  3. Use lazy loading: If you have a large number of images on a page, consider using lazy loading to improve page load times. This will only load images as they are needed, rather than all at once.

Here's an example of how to implement lazy loading using the lazy attribute:

<img src="placeholder.jpg" data-src="image.jpg" class="lazy">

And here's the JavaScript to initialize the lazy loading:

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Fallback for older browsers
    lazyImages.forEach(function(lazyImage) {
      lazyImage.src = lazyImage.dataset.src;
      lazyImage.classList.remove("lazy");
    });
  }
});
Snapey's avatar

The current approach seems to be the standard way of serving images from a Laravel application.

what bullshit @laryai

Please or to participate in this conversation.