一般的にアップロードされた画像ファイルの保存方法は下記のようになります。Laravelでは、画像アップロードのフォームから送信された画像に関してはstoreメソッドを使用すれば、簡単にサーバーに画像を保存する事が可能なのですが、画像URLのパスを取得して、直接的に画像を保存する場合は若干処理が助長的になってしまうのがネックだと思います(この部分もっとスマートに出来るよ等、アドバイスがあればコメント欄にて教えて頂けますとありがたいです!
$path = $request->file('userimage')->store('public/img');
$image = User::find(\Auth::id());
$image->image = basename($path); //imageカラムに保存
$image->save();
#前提
上記のように、アップロードされた画像ファイルの保存処理はLaravelだと簡単に書けるのですが
バッチ処理等で画像ファイルのパス(URL)を予めDBに格納した場合の、画像ファイルを保存する方法で少し躓いたのでメモ代わりに記事を執筆します。
#今回のケース
imagesテーブルに、各画像ファイルのパスが格納されているので、まずは下記のように順番に画像ファイルのパスを取得します。
$all_images = Images::get(['image_name']);
foreach ($all_images as $image) {
//DBに格納されている画像ファイル名を任意に変更したかったので、更新対象となるオブジェクトを取得
$update_image_name = Images::where('image_name', $image->image_name)->first();
//画像ファイルのURLを定義
$url = $image->image_name;
//URLからファイル名を取得(今回は画像URLの拡張子を取得して、ファイル名として保存しています)
$file_name = substr(strrchr($url,"/"),1);
//画像ファイル名の更新処理
$update_image_name->image_name = $file_name;
$update_image_name->save();
}
//ここから画像ファイル保存の処理を書く
#画像ファイルの保存処理
先程の、//ここから画像ファイル保存の処理を書くの処理を記述していきます。
//①の処理
if (strpos($url, 'AAAAAA') !== false) {
$options = array('http' => array('method' => 'GET', 'header' => 'User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',"ignore_errors"=>true));
$image_downloaded = file_get_contents($url, false, stream_context_create($options));
} else {
$image_downloaded = file_get_contents($url);
}
//②の処理
$tmp = tmpfile();
fwrite($tmp, $image_downloaded);
$tmp_path = stream_get_meta_data($tmp)['uri'];
Storage::putFileAs('public/img', new File($tmp_path), $file_name);
fclose($tmp);
#①の処理説明
$image_downloadedという変数に、file_get_contents関数を使用して画像URLから画像データを取得してます。
画像URLにAAAAA(仮のサイト名)という文字列が含まれている場合、画像URLにアクセスしようとするとForriden 403というエラーが出力されて、調べるとUser-Agentの設定が必要との事だったので適当に定義したのですが、エラーが出るので、ignore_errors"=>trueを$optionsという配列に定義して無理やりエラーを出力させないようにしております(この状態で$img_downloadedをデバッグしてみるとAWS関係のエラーが出ましたが、今の私では解決困難だと思ったので、そのまま放置してます)
#②の処理説明
①$tmp = tmpfile();
storage/app/public/imgディレクトリの直下に画像を保存する為に一時ファイルを作成
②fwrite($tmp, $image_downloaded);
一時ファイルに、画像データを書き込む
③$tmp_path = stream_get_meta_data($tmp)['uri'];
後述する画像保存処理の際、対象の一時ファイルのパスを引数に定義する必要がある為、この部分で一時ファイルのパスを取得する
④Storage::putFileAs('public/img', new File($tmp_path), $file_name)
storage/app/public/imgディレクトリ直下に画像ファイルを保存する
→Storage::putFileAsを使用して画像ファイルを保存する場合、第一引数に保存する場所、第二引数の保存対象する画像ファイルのパスを指定、第三引数に保存するファイル名を定義する。
⑤fclose($tmp);
一時ファイルを削除する(削除しないと次の画像ファイルが保存できないので)
以上が、Laravelでアップロード以外の方法で画像保存する場合の処理方法となります!
ここまで読んで頂きありがとうございます。
なんでこの部分、こう書いているのか?他にこういう方法あるよ!等アドバイスがあればコメント頂けますと非常に助かります!宜しくお願い致します。