2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

フォームからPOSTリクエストで受け取った画像サイズを小さくしてデータ容量を削減したい(Laravel10)

Last updated at Posted at 2023-07-26

やること

実現したい内容

作成しているサービスが低コストで運用していきたいため、フォームからPOSTで送られてきた画像をController内でサイズ変更してから保存したいと思いました。

方法

オープンソースのPHP画像処理および操作ライブラリであるInterventionImageを使用していきます。
Laravel(PHP)で画像処理といえばこれって感じのライブラリのようです。

環境

Dockerで作成したローカル環境で実施

  • PHP: 8.1.18
  • Laravel10
  • nginx: 1.24.0
  • mysql: 8.0

やったこと

InterventionImageをインストール

composerを使ってインストールします。

composer require intervention/image

インストールすると、composer.jsonとcomposer.lockが更新されます。

サービスプロバイダとエイリアスを登録しておきます。

config/app.php
'providers' => ServiceProvider::defaultProviders()->merge([
    ...中略
    Intervention\Image\ImageServiceProvider::class,
])->toArray(),

'aliases' => Facade::defaultAliases()->merge([
    'Image' => Intervention\Image\Facades\Image::class,
])->toArray(),

InterventionImageのインストールはこれだけで完了です。

Controllerでサイズ変更する

ItemPostController.php
use Image;
public function store(Request $request)
{
    $itemPost = new ItemPost();
    ...中略
    if (request('image')) {
        $name = date('Ymd_His') . '_' . request()->file('image')->getClientOriginalName();
        $image = request()->file('image');
        $image = Image::make($image);
        // 圧縮
        $image->resize(
            300,
            null,
            function ($constraint) {
                $constraint->aspectRatio();
                $constraint->upsize();
            }
        )->orientate();
    
        $image->save('storage/images/' . $name, 60);
        $itemPost->image = $name;
    }
    $itemPost->save();
}

上記でサイズ変更に成功しました。
内容を説明していきます。
$name = date('Ymd_His') . '_' . request()->file('image')->getClientOriginalName();
requestで受け取った画像の名前に日付を追加した文字列をファイル名として$nameに格納しておきます。
画像処理には関係ないので省略しますが、最後のところで$itemPostをDBに保存しています。

$image = request()->file('image');
$imageにリクエストで受け取ったファイルを格納します。

$image = Image::make($image);
use宣言したImageを利用して、InterventionImageを使用しています。
make関数でリクエストの画像からイメージインスタンスを作成しています。

$image->resize(
    300,
    null,
    function ($constraint) {
        $constraint->aspectRatio();
        $constraint->upsize();
    }
)->orientate();

resize関数でサイズを変更しています。
横幅を300pxにリサイズしています。aspectRatioを設定することで縦横比は原本のままにしています。upsizeは画像が拡大されないようにしています。
orientate関数はEXIF画像プロファイル設定「方向」を読み取り、画像を回転して画像を正しく表示するメソッドになります。使用することで勝手に画像が反転する現象を解消しております。後述しますが、orientateを使用する場合はexifサポートを有効にする必要があります。

$image->save('storage/images/' . $name, 60);
イメージインスタンスをstorage/images/ファイル名 のパスに品質「60」で保存しています。

上記で、storage/images/ファイル名 のパスに画像処理後の画像が保存される形になります。

トラブルシューティング

エラー1: InterventionImageを使用するにはGDサポートを有効にする必要がある

GD Library extension not available with this PHP installation. というエラーが発生しました。
GDがインストールされていませんというエラーになります。GDをインストールすることで改善されました。
GDのインストール: https://www.php.net/manual/ja/image.installation.php

具体的には、Dockerを使っているので、以下をPHPのDockerfileに追加しました。

RUN apt-get install -y zlib1g-dev \ 
    libzip-dev \
    libjpeg-dev \
    libpng-dev \
    libfreetype6-dev \
    libjpeg62-turbo-dev

RUN docker-php-ext-install pdo_mysql zip
RUN docker-php-ext-configure \
    gd --with-freetype --with-jpeg

GDがJPEG等のフォーマットを扱えるようにオプションを指定しています。

エラー2: exifサポートが有効になっていない

Reading Exif data is not supported by this PHP installation. というエラーが発生しました。

画像が勝手に回転してしまう現象を改善するために$image->orientate()を使用しました。
orientateを利用するためにexifサポートを有効にする必要がある。

PHPのDockerfileに以下を設定することで改善しました。

RUN docker-php-ext-configure \
    gd --with-freetype --with-jpeg
# 以下を追加
RUN docker-php-ext-install -j$(nproc) gd exif

(参考)1MB以上の画像がフォームから送信できない場合

413 Request Entity Too Large というエラーが出た時
以下3つのデータサイズが設定されているか確認する。

  • nginx・設定ファイルのclient_max_body_size(もしあるなら変更、なければ追加)
  • php.iniのpost_max_size
  • php.iniのupload_max_filesize

自分はnginxのdefault.confに下記を追加して改善した。

default.conf
client_max_body_size 64m;

参考: https://blog.capilano-fw.com/?p=256

まとめ

初めてInterventionImageを使用したので、ちょこちょこエラーが出てしまいましたが、とても簡単に画像加工できることが分かりました。ドキュメントも関数ごとにまとまっていて見やすく、モザイク処理やテキスト挿入などできることは多いので、他のサービスを作る時に画像処理が必要だった場合は、また利用したいと思いました。

2
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?