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

 

環境は、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制作会社・システム開発会社です。東京都及びその近郊(首都圏)を中心として、SEO対策を意識したPC及びスマホのサイトをワンソース(レスポンシブ対応)で制作します。

実績

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

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

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

東京のホームページ制作・Web制作のお問い合わせ、お見積り依頼、相談、質問は
こちらのお問い合わせフォームよりお願いいたします

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