2023.07.27 Web制作
大量の画像のリサイズをする処理
環境は、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制作のお問い合わせ、お見積り依頼、相談、質問は
こちらのお問い合わせフォームよりお願いいたします