大量の画像のリサイズをする処理

 

環境は、Laravel9、php8.2です。

画像リサイズには、InterventionImage ライブラリを使用しています。こちらの設定方法については、各詳細ページでご確認ください。

今回は、多数の詳細ページが発生するサイトにおいて、画像を色んな人が投稿できるのですが、この画像がスマホだったり、デジカメだったりと、様々なファイルサイズの画像が投稿されており、表示に負荷がかかってきたので、これらを一気にリサイズする処理を作ってみました。

今回は約4000ディレクトリあり、それぞれ平均で10個のファイルがはいっており、それらの画像の幅を一律で980pxにします。

処理はCommandを使って処理することにしました。

まずは完成版が下記になります。

<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
use InterventionImage;

class resizeImages extends Command
{
	protected $signature = 'command:resizeImages';

	protected $description = '大きいサイズの画像をリサイズ';

	public function __construct()
	{
		parent::__construct();
	}

	public function handle()
	{
	    // ディレクトリ一覧の取得
	    $directories = Storage::disk('images')->directories();
	    // ディレクトリを一つずつループ
	    foreach($directories as $d) {
	        // ディレクトリ内のファイル一覧を取得
	        $files = Storage::disk('images')->files($d);
	        // ファイルを一つずつループ
	        foreach($files as $f) {
	            // ファイルのパスを取得
	            $path = Storage::disk('images')->path($f);
	            try {
    	            // 画像情報を取得
	                $image_size = getimagesize($path);
	            } catch (\Exception $e) {
                  // 画像情報を取得できない場合
	                continue;
	            }
	            try {
    	            // 画像の幅が980pxに満たない場合は無視
	                if($image_size[0] <= 980) continue;
	            } catch (\Exception $e) {
	                // $image_sizeがfalseを返す場合
	                continue;
	            }
              try {
                  InterventionImage::make($path)->resize(980, null, function ($constraint) {
                      // 縦横比を保持したままにする
                      $constraint->aspectRatio();
                      // 小さい画像は大きくしない
                      $constraint->upsize();
                  })->save($path);
              } catch (\Exception $e) {
                  // InterventionImageがdecodeできない場合
                  continue;
              }
	        }
	    }
	}

今回は、Storageファサードを多用しています。

Storageのdiskにある文字列は、config/filesystem.phpで「images」というdiskを設定した想定です。

こういう処理の場合の肝となるのは、エラーが出た場合の処理だと思います。

この処理は、毎日深夜に回し、新しく追加された画像についても処理されるようにしました。

いますぐ利用したい場合には、SSHで接続できるのであれば、Laravelのartisanコマンドが利用できるディレクトリまで移動して、コマンドラインで下記のように入力します。

$ cd /var/www/laravel
$ php artisan
Laravel Framework 9.28.0

Usage:
  command [options] [arguments]

Options:
~
 cache
  cache:clear                   Flush the application cache
  cache:forget                  Remove an item from the cache
  cache:table                   Create a migration for the cache database table
 command
  command:resizeImages          大きいサイズの画像をリサイズ
~

laravelのディレクトリは環境によってことなるとおもいますが、php artisanと実行し、コマンド一覧が表示されれば、コマンドから実行できます。

cacheのすぐ下にcommandのところに作成したコマンドが表示されているはずです。

そこで下記のようにコマンドを入力します。

$ php artisan command:resizeImages

これで処理が開始されます。いきなり全処理が怖い場合には、ddなどを利用して状況を確認しながらすすめるといいと思います。

また、Controllerから実行したい場合には下記のようにControllerに記述します。

~
use Illuminate\Support\Facades\Artisan;

class HomeController extends Controller
{
    public function index()
    {
        Artisan::call('command:resizeImages');
    }
}

これによりindexにアクセスすれば、処理が開始されます。ただ、phpの設定などにより重い処理はTimeoutが発生する場合がありますが、このエラーについては、エラー自体を検索すれば各所で説明があると思います。

今回の場合は、scheduleでコマンドを設定し、深夜に処理をするようにしました。

<?php

namespace App\Console;

use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;

class Kernel extends ConsoleKernel
{
    protected function schedule(Schedule $schedule)
    {
        $schedule->command('command:resizeImages')
                 ->dailyAt('4:00')
                 ->withoutOverlapping()
                 ->appendOutputTo(storage_path('logs/resize_images.log'));
    }

    protected function commands()
    {
        $this->load(__DIR__.'/Commands');

        require base_path('routes/console.php');
    }
}

これで毎朝4時に処理がおこなわれます。

withoutOverlapping()は多重起動が起きないようにする設定ですが、毎回癖のようにいれているだけで、必要はないと思います。

また、appendOutputTo()でログを吐き出します。深夜の処理で止まってしまった場合に、storage/logs/ディレクトリに「resize_images.log」というファイル名で吐き出されます。

まとめ

こういう処理は日々発生します。後で再利用するためにメモ書きとして残しました。レアなケースですが何かのお役に立てれば!!

文責:フライング・ハイ・ワークス代表 松田 治人(まつだ はるひと)
会社では、Laravelを中心としたエンジニアとして働いており、これまでに50本以上のLaravelによるWebアプリケーションやWebサイトを構築しています。
エンジニアとして弊社で働きたい方、お仕事のご相談など、お待ちしております。

WEBサイト制作のお問い合わせ、お見積り依頼、ご質問は
こちらのお問い合わせフォームよりお願いいたします

メールお問い合わせはこちら

フライング・ハイ・ワークスの紹介

フライング・ハイ・ワークスは、東京都渋谷区にある2000年3月創業のシステム開発にも対応できるデザインも強いWeb制作・ホームページ制作会社です。東京都及びその近郊(首都圏)を中心として、SEO対策を意識したPC及びスマホのサイトをワンソース(レスポンシブ対応)で制作します。

実績

デザイナーチームは、グラフィックデザインやイラストの制作も得意としており、著作権を意識しない素材の提供が可能です。システム・コーディングチームでは、Laravelなどを使用したスクラッチからのオリジナルシステムの構築を始め、WordPressのカスタマイズを得意としております。

また、SEOやランディングページ(LP)、広告向けバナーなどを他社様でやっていた作業の引継ぎでも問題ありません。制作実績は多数ございますので、お客様に合わせたご提案が可能です。

500点以上のフライング・ハイ・ワークスの制作実績ページをご覧ください!

採用

FHWでWebディレクター、Webデザイナー、Webプログラマーやシステム開発者として働いてみたいと思っていただける方は、下記にて定期的に募集をしておりますので、ぜひ、ご応募ください。

WEBサイト制作のお問い合わせ、お見積り依頼、ご質問は
こちらのお問い合わせフォームよりお願いいたします

メールお問い合わせはこちら