Quantcast
Channel: 配列タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 821

laravelで画像を配列で保存し、vue.jsで表示

$
0
0

ポートフォリオでinstagramのような写真共有のアプリを作る際に初心者の俺はとりあえず思いついたアイデアで写真の保存と表示をやってみた。
今後改善していく予定なので、現在の仕様をとりあえず記念に掲載。

post.vue
<template><div><inputref="input"type="file"multiple@input="load"></div><div><button@click="submit">送信</button></div></template><script>exportdefault{data(){return{base64Images:'',}},methods:{load(){constfiles=this.$refs.input.files;//ref="input"の要素のfilesvaruploadedBase64Images=[];//複数のimageのアップロードを想定し、格納する配列を準備for(vari=0;i<files.length;i++){//for文をfilesの数だけ回すためにfiles.lengthconstreader=newFileReader();letthat=this;reader.onload=(function(event){postArray.unshift(event.target.result);//unshiftは先頭にデータを入れる。pushは末尾});reader.readAsDataURL(files[i]);}this.base64Images=postArray;//https://qiita.com/popo62520908/items/d707ff2010be78f97a50 でreaderの復習},submit(){letfd=newFormData();//fileを使うためfd.append("images",JSON.stringify(this.base64Images));//postを使うときは、JSON.stringify()を使って配列を文字列にaxios.post('/api/create',fd).then(response=>(window.location.href='/')//処理が完了後homeに戻す).catch(function(error){console.log(error);});},}}</script>

formでfileを含む時のContent-Typeは、multipart/form-dataになるので、new FormData()を使います(fileは文字、画像など様々な種類のデータを取り扱うため)。
とどこかのサイトに書いてあり、postはJSON.stringfy()で文字列に変換しなければと書いてあったのだが、以下のやり方でもいけた。

post.vue
<script>exportdefault{data(){return{base64Images:'',}},methods:{submit(){varparam={images:this.base64Images,}axios.post('/api/posts',param).then(response=>(window.location.href='/')//処理が完了後homeに戻す).catch(function(error){console.log(error);});},}}</script>

次にサーバー側のデータ受け取り、保存。

PostController
<?phpnamespaceApp\Http\Controllers;useIlluminate\Http\Request;useApp\Post;useIlluminate\Support\Facades\Storage;classPostControllerextendsController{publicfunctionindex(){returnview('post');}publicfunctioncreate(Request$request){$post=newPost;//インスタンス作成$decoded_images=json_decode($request->images);//文字列化されたjsonを配列に戻す。$src_array=[];//この中に保存するファイル名を格納し、データベースに保存する。for($i=0;$i<count($decoded_images);$i++){//vueで作ったload()関数と似た感じの処理。$base64_image=$decoded_images[$i];@list($type,$file_data[$i])=explode(';',$base64_image);//explodeで$base64_imageないの文字列を分割し、list関数で分割したデータを変数$typeと$file_data[$i]に格納。//つまりdata:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAA....が//$type = 'data:image/jpeg;';//$file_data[$i] = 'base64,/9j/4AAQSkZJRgABAQEASABIAA....';//ということ@list(,$file_data[$i])=explode(',',$file_data[$i]);//更にこの処理によって//$file_data[$i] = 'base64,/9j/4AAQSkZJRgABAQEASABIAA....';が//$file_data[$i] = '/9j/4AAQSkZJRgABAQEASABIAA....';//になる$imageName=str_random(10).'.'.'png';//$file_data[$i]の名前を作成。str_random()関数を作ってランダムにStorage::disk('local')->put($imageName,base64_decode($file_data[$i]));//diskは保存場所。詳しくは/config/filesystems.phpで設定。//localに$imageNameという名前でbase64_decode($file_data[$i])のデータを保存しますということ。//use Illuminate\Support\Facades\Storage;忘れずに$array[]=$imageName;//この$imageNameを配列化$src_array+=$array;//格納}$post->image=json_encode($src_array);//$src_arrayは['RgABAQEASA.png','SkZJRgABAQ.png']こんな感じで、このままでは保存できないのでjson_encodeで文字列、"['RgABAQEASA.png','SkZJRgABAQ.png']"に変換。$post->save();//そして保存}}

いい記事発見したので掲載
https://qiita.com/PlanetMeron/items/2905e2d0aa7fe46a36d4
list関数はこちらを
https://www.sejuku.net/blog/24406

ちなみにJSの new FormDataを使わない場合

PostController
publicfunctioncreate(Request$request){$post=newPost;$post->save();$decoded_images=$request->images;//$decoded_imagesも何も、最初から文字列にエンコードされていないのだが、以下の書き換えが面倒なので変数$decoded_imagesに格納$src_array=[];for($i=0;$i<count($decoded_images);$i++){$base64_image=$decoded_images[$i];@list($type,$file_data[$i])=explode(';',$base64_image);@list(,$file_data[$i])=explode(',',$file_data[$i]);$imageName=str_random(10).'.'.'png';Storage::disk('local')->put($imageName,base64_decode($file_data[$i]));$array[]=$imageName;$src_array+=$array;}$post->image=json_encode($src_array);$post->save();}

当時は配列ではなくオブジェクトで保存していた。
そもそも配列とオブジェクトの違いもわからなかった。
本当に懐かしい。笑

show.vue
<template><div><divv-for="(parsedUserPost, index) in parsedUserPosts"><v-carousel><v-carousel-itemv-for="(image,i) in parsedUserPost.image":key="i":src="'storage/image/' + image"></v-carousel-item></v-carousel></div></div></template><script>exportdefault{data(){return{userPosts:'',//←propsおよびajaxでの値を受け取っている前提}},computed:{parsedUserPosts(){varuserPosts=this.userPosts;if(userPosts.length==0){returnfalse;//this.userPostsがundefinedの歳エラーが出るためこの処理}else{for(vari=0;i<userPosts.length;i++){userPosts[i].image=JSON.parse(userPosts[i].image);//JSON.parse()を使って文字列だった配列をもとに戻す。//"['RgABAQEASA.png','SkZJRgABAQ.png']"こんな感じで保存されているので、['RgABAQEASA.png','SkZJRgABAQ.png']に戻してあげる。}returnuserPosts;}},}}</script>

JSON.parseを使っているが、コントローラーでjson_decode()を使っても行けるはず。
これだけですごい勉強になった気がするな。当時の思いつきで突き進んだ結果。


Viewing all articles
Browse latest Browse all 821

Latest Images

Trending Articles