laravel 图片库优化

问题描述 投票:0回答:2

我有照片库页面,其中显示给定目录中的所有文件。 我处理图片的逻辑如下:

  • 我保存在里面的原始图片
    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 被删除。我找不到办法保留它。也许这就是我收到网关超时的主要原因。我想我有两个问题:

  1. 从大源文件获取 EXIF 比从拇指获取 EXIF 需要更长的时间,但我不知道如何将 exif 数据从源图像复制到拇指。
  2. 我一次从目录中的所有文件中检索 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>
php laravel image intervention
2个回答
0
投票

当您清楚地表明从大文件中检索 EXIF 数据很慢时,我不明白您为什么不将这些东西放入数据库中。您不想在每个页面加载时做繁重的工作。

您也只能轻松过滤数据,只要它不在数据库表中即可。

您当前的代码编写得很糟糕并且性能不佳(您正在从图像中检索页面标题???),因此解决方法是设计一些数据库表来处理这个问题:)。一旦完成,我打赌你可以将这个控制器缩小到 7 行以下。


0
投票

请求过程中应尽量避免密集或耗时的处理,以获得更好的用户体验。

优化工作流程的一种方法是:

为类别创建数据库表

创建

image_categories
包含列的表格

  • 名称(字符串)
  • slug(字符串)(唯一)
  • title(string): exif('ImageDescription') 或任何值
  • exif(text):如果需要,类别图像的完整 exif 数据
为图像创建数据库表

创建包含列的

images

  • image_category(string): 图像类别的slug
  • src(string): 原始图像的路径
  • src_thumb_md(字符串):thumb_md(300 x 300)图像的路径
  • src_thumb_lg(string):thumb_lg (1024 x 768) 图像的路径
  • 描述(字符串):exif('ImageDescription')
  • exif(text):如果需要,图像的完整 exif 数据
创建图像缩略图时存储数据

将用于生成缩略图的控制台命令扩展为

  • 将所有图像的路径和 exif 数据存储到
    images
    表中
  • 存储类别图像时将标题和 exif 数据存储到
    image_categories
    表中
定义具有关系的图像和 ImageCategory 模型(可选)
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>
© www.soinside.com 2019 - 2024. All rights reserved.