laravel8でs3にアップロードするAPIを作ってみる
1. lightsailにlaravelをインストール
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#ドキュメントルートを変更 vi /opt/bitnami/apache/conf/bitnami/bitnami.conf DocumentRoot "/opt/bitnami/apache/htdocs/laravel/public" <Directory "/opt/bitnami/apache/htdocs/laravel/public"> # Webサーバ再起動 sudo /opt/bitnami/ctlscript.sh restart apache #storageのパーミッションを sudo chmod -R 777 /opt/bitnami/apache/htdocs/laravel/storage # MySQLのrootのパスワードは、ホームディレクトリにある cat /home/bitnami/bitnami_application_password |
2. Uploadモデルを作る
1 |
php artisan make:model Upload --all |
routes/api.php
1 2 3 4 |
// laravel8からroutes/web.phpやapi.phpにも、useが必要! use App\Http\Controllers\UploadController; Route::post('/', [UploadController::class, 'store']); Route::get('/{hash_id}', [UploadController::class, 'show']); |
テーブル定義
1 2 3 4 5 6 7 |
Schema::create('uploads', function (Blueprint $table) { $table->id(); $table->string('upload_file_name')->comments('元のファイル名'); $table->string('upload_file_hash')->comments('ハッシュ化されたファイル名(拡張子付き)'); $table->string('upload_hash_id')->comments('ハッシュID(拡張子なし)'); $table->timestamps(); }); |
App\Http\Controllers\UploadController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
use Exception; use Illuminate\Support\Facades\Storage; public function store(Request $request) { try { $upload = new Upload(); //アップロードされたファイル名は使わず、ハッシュ値と拡張子にする(セキュリティのため) $file_hash_id = hash("sha256", uniqid(rand(), true)); $original_file_name = $request->file('file')->getClientOriginalName(); $ext = $request->file('file')->getClientOriginalExtension(); // WebサーバとMySQLレコードに保存するファイル名 $file_hash = $file_hash_id .".".$ext; $path = $request->file('file')->storeAs('uploads', $file_hash); // MySQLレコードに保存するファイル名とハッシュ名 $data['upload_file_name'] = $original_file_name; // 元のファイル名 $data['upload_file_hash'] = $file_hash; // ハッシュ化されたファイル名(拡張子付き) $data['upload_hash_id'] = $file_hash_id; // ハッシュID(拡張子なし) $upload->fill($data); $upload->save(); return response()->json([ 'path' => $path ]); } catch (Exception $e) { return response($e->getMessage(), 500); } } public function show($hash_id) { try { $upload = Upload::where('upload_hash_id', $hash_id)->firstOrFail(); return $upload; } catch (Exception $e) { return response($e->getMessage(), 500); } } |
3. postmanでアップロードしてみる。
Bodyのform-dataを選択して、keyをfileと入力したら、その欄の右側にマウスカーソルを移動させるとtextかfileが選択できる表示が出てくるのでfileを選択。分かりづらい!
レスポンスが返ってくる
{
“path”: “uploads/nM6sBokos4jMAmFdnBueoSf0fciI94uqW5Er5p7g.txt”
}
curlだとうまくアップロード出来なかった…。
1 |
curl -X POST -H "Accept: application/json" http://ligthsailの公開IP/api -f "file=a.txt" |
4. アップロード先をS3に変更
laravel8からs3へ画像アップロードしてみる。署名付きURL(期限付きURL)を生成して、S3に一時的に読み取り可能にする。
.envでアップロード先S3設定をしておく
1 2 3 4 5 6 7 8 9 |
// $path = $request->file('file')->storeAs('uploads', $file_hash); // S3にアップロード(/uploadsフォルダ内に) $path = Storage::disk('s3')->putFile('/uploads', $request->file('file')); // アップロード先のURLを取得 $upload_url = Storage::disk('s3')->url($path); return response()->json([ 'upload_url' => $upload_url ]); |
5. s3の公開設定が間違っていなければ、このままURLでアップロードしたファイルが公開される。