読者です 読者をやめる 読者になる 読者になる

LaravelでS3に画像アップロードしようと思ったらエラー

league/flysystem-aws-s3-v3 を使って画像アップロードしようとしたら怒られました。
クライアント側ではなくサーバ側でアップロード処理を行うケースです。
リソース型でも文字列型でもないオブジェクトをアップロードメソッドに渡してアップロードしようとしていたことが原因でした。

以下ボツコードです。

$postedFile = Input::file ('InputImage');
$uploadImage = Image::make($postedFile);
$uploadImage->resize(100, 100);
$fileName = "hoge.jpg"
$storage = Storage::disk('s3');
$storage->put($fileName,$uploadImage);

エラーはこちら。

ErrorException in Util.php line 258:
fstat() expects parameter 1 to be resource, object given

どうやらファイルサイズを調べるために fstat() メソッドを使っているようで、その fstat() はリソース以外は受け付けてませんとのことです。
ここで言うリソースとは、PHP のリソース型のことみたいです。
PHP に手を付けて間もないのでリソースと言われた時に、すぐに「ああリソース型ね」とはならず...orz。
PHP マニュアルを読んでなんとなく把握できました。

リソースは特別な変数であり、外部リソースへのリファレンスを保持しています。 います。リソースは、特別な関数により作成され、使用されます。 これらの関数および対応する全てのリソース型の一覧については、 付録 を参照ください。

ということで、以下のようなコードであればアップロードできます。

$fileName = "hoge.jpg"
$fp = fopen($fileName, "r"); 
$disk = Storage::disk('s3');
$disk->put($name,$fp);
fclose($fp);

また、AwsS3Adapter が実際にファイルサイズを調べている処理の手前まで遡ってみると、

$options['ContentLength'] = is_string($body) ? Util::contentSize($body) : Util::getStreamSize($body);

と書いてありました。
文字列型でもいけそうですね。
ちなみに先ほどの fstat() は上記 getStreamSize() 内で呼ばれています。

$postedFile = Input::file ('InputImage');
$uploadImage = Image::make($postedFile);
$payload = (string) $uploadImage->encode();
$fileName = "hoge.jpg";
$disk = Storage::disk('s3');
$disk->put($fileName,$payload);

文字列型でも無事投稿できました。
おわり。