I have photo gallery page, which shows all files from given directory.
I have following logic of handling pictures:
- original pictures I keep inside
storage/app/img
- using console command and
InterventionImage
library I create thumbs – inpublic/thumbs_md
I keep small thumbs about 300×300 and inpublic/thumbs_lg
I keep the same pictures, but 1024×768.
My idea about gallery page is that I find all files from given directory inside thumbs_md
and show them as thumbs with the links to the files with the same names inside thumbs_lg
.
And each picture should have description, which I take from $image->exif('ImageDescription')
using InterventionImage
library.
And paginate results with 20 pictures on the page.
It works well with less than 200 pictures in the directory, but when it is more nginx gives me 504 Gateway Time-out.
I found that the reason in getting description from exif.
EXIF info stored only in original source pictures inside storage/app/img
. During thumbs generating EXIF is deleted. I could’t find a way to keep it. Maybe this is main reason why I get Gateway Time-out. I guess that I have 2 problems:
- It takes longer time to get EXIF from big source file rather than from thumb, but I don’t know how to copy exif data from source image to thumb.
- I retrieve exif data from all files in directory at once, but I don’t know how to split it into chunks, because I must to give all elements to paginator at once.
At the moment I just comment code where I read EXIF from all files and there is no problems, but I want to get those descriptions and I don’t really want to keep image description in database. I like the fact that it is part of image.
Is there a way to optimise my code?
controller
public function item($slug)
{
$files = Storage::disk('storage')->allFiles('thumbs_md/'.$slug);
$links = Storage::disk('storage')->allFiles('thumbs_lg/'.$slug);
if ( empty($files) ){
abort(404);
}
// generate title of the page
try {
$image = Image::make( '/var/www/storage/app/img/categories/'. $slug.'.jpg');
}
catch(NotReadableException $e)
{
// If error
$title = 'Picture not found';
}
// If no error ...
$title = $image->exif('ImageDescription');
// generate description for picture
$ImageDescription = function($value) {
try { $image = Image::make(str_replace('thumbs_md', '/var/www/storage/app/img', $value)); }
catch(NotReadableException $e)
{
// If error
return 'Picture not found';
}
// If no error ...
return $image->exif('ImageDescription');
};
//$imgDesc = array_map($ImageDescription, $files);
for ($i=0; $i < count($files); $i++) {
$items[$i]['thumb'] = $files[$i];
$items[$i]['link'] = $links[$i];
//$items[$i]['description'] = $imgDesc[$i];
}
$items = Arr::arrayToObject($items);
$items = collect($items)->mypaginate($perPage = 20);
$items->title = $title;
$items->slug = $slug;
return view('pages.gallery.item', compact('items'));
}
view
<div class="gallery">
@foreach ($items as $item)
<a href="/storage/{{ $item->link }}" class="lightGallery">
<img {{-- alt="{{ $item->description }}" --}} src="/storage/{{ $item->thumb }}">
{{-- <p>{{ $item->description }}</p> --}}
</a>
@endforeach
</div>
2
Answers
I don’t see why you would not put this stuff in a database, when you’ve clearly shown that retrieving EXIF data from a big file is slow. You don’t want to be doing heavy work on each page load.
You are also limited to filtering data easily as long as it is not in a database table.
The code you have currently is badly written and not performant (you are retrieving the page title from an image???) so the way to go is to design a few database tables to handle this :). Once it is done, I bet you can shrink this controller to under 7 lines.
Intensive or time consuming processing should be avoided during request as far as possible for better user experience.
One way to optimise your workflow would be:
Create database table for categories
Create
image_categories
table with columnsCreate database table for Images
Create the
images
table with columnsStore the data when creating thumbnails for image(s)
Extend the console command which you are using to generate the thumbnails, to
images
table for all imagesimage_categories
table when storing the image for categoryDefine Image and ImageCategory models with relations (optional)
Controller & View
If Models are defined
Or when models are not defined