我有照片库页面,其中显示给定目录中的所有文件。 我处理图片的逻辑如下:
storage/app/img
Intervention\Image
库创建拇指 - 在public/thumbs_md
中我保留约300x300的小拇指,在public/thumbs_lg
中我保留相同的图片,但是1024x768。我对图库页面的想法是,我找到
thumbs_md
内给定目录中的所有文件,并将它们显示为拇指,并带有指向thumbs_lg
内同名文件的链接。
每张图片都应该有描述,这是我使用 $image->exif('ImageDescription')
库从 Intervention\Image
获取的。
并对结果进行分页,页面上有 20 张图片。
它适用于目录中少于 200 张图片,但当目录中图片较多时,nginx 会给我 504 网关超时。
我发现这是从 exif 获取描述的原因。
EXIF信息仅存储在原始源图片里面storage/app/img
。在拇指生成过程中,EXIF 被删除。我找不到办法保留它。也许这就是我收到网关超时的主要原因。我想我有两个问题:
目前我只是注释从所有文件读取 EXIF 的代码,没有问题,但我想获得这些描述,并且我真的不想将图像描述保留在数据库中。我喜欢它是图像的一部分这一事实。 有没有办法优化我的代码?
控制器
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'));
}
查看
<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>
当您清楚地表明从大文件中检索 EXIF 数据很慢时,我不明白您为什么不将这些东西放入数据库中。您不想在每个页面加载时做繁重的工作。
您也只能轻松过滤数据,只要它不在数据库表中即可。
您当前的代码编写得很糟糕并且性能不佳(您正在从图像中检索页面标题???),因此解决方法是设计一些数据库表来处理这个问题:)。一旦完成,我打赌你可以将这个控制器缩小到 7 行以下。
请求过程中应尽量避免密集或耗时的处理,以获得更好的用户体验。
优化工作流程的一种方法是:
创建
image_categories
包含列的表格
创建包含列的
images
表
将用于生成缩略图的控制台命令扩展为
images
表中image_categories
表中class ImageCategory extends Model
{
public function images()
{
return $this->hasMany(ImageCategory::class, 'image_category');
}
}
class Image extends Model
{
public function imageCategory()
{
return $this->belongsTo(ImageCategory::class, 'image_category', 'slug');
}
}
如果定义了模型
public function item($slug)
{
$category = ImageCategory::where('slug', $slug)->first();
$images = $category->images()->paginate(20);
return view('pages.gallery.item', compact('category', 'images'));
}
或者当模型没有定义时
public function item($slug)
{
$category = DB::tables('image_categories')->where('slug', $slug)->first();
$images = DB::table('images')->where('image_category', $slug)->paginate(20);
return view('pages.gallery.item', compact('category', 'images'));
}
<div class="gallery">
<h1>{{ $category->title }}</h1>
@foreach ($images as $image)
<a href="/storage/{{ $image->src_thumb_lg }}" class="lightGallery">
<img {{-- alt="{{ $image->description }}" --}} src="/storage/{{ $image->src_thumb_md }}">
{{-- <p>{{ $image->description }}</p> --}}
</a>
@endforeach
<!-- Pagination links -->
{{ $images->links() }}
</div>