タイトルの通りです。画像やファイルのstorage保存の記事はいくつか見かけましたが、jsからPOSTする記事についてはあんまり見かけなかったので書きました。
この記事ではaxios経由で画像をPOST、LaravelのAPI処理に渡しているサンプルコードを簡単に説明します。概要は以下の通りです。
- canvasに画像を描画し、blobデータを作成
- blobをformDataにappendして、axiosでPOST
- POSTされたblobファイルを、Laravel API側で処理・保存
View側の処理
データのBLOB化
以下の処理かtoBlob
を使ってCanvasに描画した画像ファイルをblob化します。
index.vue
// Canvasのデータをblob化
const type = 'image/png';
const dataurl = this.canvas.toDataURL(type); // this.canvasは用途に合わせて書き換え
const bin = atob(dataurl.split(',')[1]);
const buffer = new Uint8Array(bin.length);
for (let i = 0; i < bin.length; i++) {
buffer[i] = bin.charCodeAt(i);
}
const blob = new Blob([buffer.buffer], {type: type});
"multipart/form-data
のデータをPOSTするので、blobファイルをFormData
インタフェースにappendする形でデータを作成します。
index.vue
const data = new FormData();
data.append('photo', blob, 'image.png'); //'photo'というkeyで保存
blobを格納したdataをaxios.post
の第二引数にセットすれば、POST可能です。
index.vue
axios.post('/api/photo', data, {
headers: { 'content-type': 'multipart/form-data' }
})
.then(res => {
console.log('success')
}).catch(error => {
new Error(error)
});
Laravel API側の処理
api用のControllerで設定したstore
定義内に、受け取ったblobデータをファイルとして保存するための処理を書きます。View側でFormData
内にappendしたphoto
データを$request
から参照し、storeAs
メソッドを実行することで簡単に保存が可能です。
IndexController.php
public function store(Request $request)
{
// ファイル名を取得
$filename = $request->photo->name;
// blobデータをstorageに保存する
// diskの指定を特にしなければ、例の場合。`storage/app/images/`に画像が保存される
$path = $request->photo->storeAs('images', $filename);
}