はじめに
数回に分けてNuxt.jsプロジェクトでデータの永続化を行う方法を解説しています。これらの記事は上から順番に読んでいくことを想定しています。
- Nuxt.jsプロジェクトでFirestoreを利用したデータの永続化/取り出しの実装方法
- Nuxt.jsプロジェクトでいろいろな条件を指定してFirestoreからデータを取得する
- Nuxt.jsプロジェクトでFirestoreのデータを変更/削除する
- Nuxt.jsプロジェクトでFirebase Storageに画像ファイルをアップロードする
- Nuxt.jsプロジェクトでFirebase Storageにアップロードした画像を変更/削除する
これらの記事で作成したNuxt.jsプロジェクトは以下のGitHubリポジトリーで公開しています。
GitHub - whitia/nuxt-firebase-sample
前回まではFirestoreを利用して名前や年齡といったテキストベースのデータ永続化などを行いました。
今回はFirebase Storageを利用して画像を保存したいと思います。これまでユーザー情報について扱ってきたので、各ユーザーにアバターを設定できるようにしていきます。
概念図
(1) uploadImage
アクションでFirebase Storageに画像を保存します。
(2) (1)の戻り値で保存した画像のURLが返されます。
(3) (2)のURLをaddUser
アクションに渡します。
(4) ユーザー情報のimage
フィールドに画像のURLを保存します。
準備
事前にFirebase Storageのバケットを作成しておいてください。また、作成したバケットのセキュリティルールを以下のページを参考にして行ってください。
Storage セキュリティ ルールを使ってみる | Firebase
実装
pages/users/create.vue
に以下を修正/追記します。
<template>
<!-- 以下を修正 -->
<b-form @submit.prevent="addUser" enctype="multipart/form-data">
<div class="container mt-5">
...
<!-- 以下を追記 -->
<div class="row justify-content-center">
<div class="col-12 col-sm-3">
Image
<b-form-file
v-model="user.avatar"
placeholder="画像ファイルを選択してください"
drop-placeholder="画像ファイルをドラッグ&ドロップしてください"
accept="image"
id="avatar"
class="mb-3"
required
plain
></b-form-file>
</div>
</div>
...
</div>
</b-form>
</template>
<script>
export default {
data() {
return {
user: {
name: {
first: null,
last: null
},
age: null,
// 以下を追記
avatar: null
}
}
},
methods: {
addUser() {
// 以下を修正
this.$store.dispatch('uploadFile', {
file: this.user.avatar
})
.then(response => {
this.user.id = response.name
this.user.avatar = response.url
this.$store.dispatch('addUser', { user: this.user })
.then(() => {
setTimeout(() => {
this.$router.push('/users')
}, 1000)
})
})
}
}
}
</script>
ファイル選択フォームを追加しました。Bootstrap-Vueのaccept="image"
というプロパティを設定することで画像ファイルのみができるようになります。
addUser
メソッドを修正します。まずVuexストアのuploadFile
メソッドで画像をFirebase Storageに保存し、保存した画像のURLをユーザー情報に付け足してユーザー情報を保存しています。
addUser
が完了した1秒後にユーザー一覧画面に遷移します。
store/index.js
に以下を追記します。
import { v4 as uuidv4 } from 'uuid';
import firebase from '~/plugins/firebase'
// 以下を追記
import 'firebase/storage'
const db = firebase.firestore()
const usersRef = db.collection('users')
// 以下を追記
const firestorage = firebase.storage()
export const state = () => ({
users: [],
user: {
id: '',
name: {
first: '',
last: ''
},
age: ''
}
})
export const actions = {
addUser({ commit }, payload) {
const user = {
// 以下を修正
id: payload.user.id,
name: payload.user.name,
age: payload.user.age,
// 以下を追記
avatar: payload.user.avatar,
created_at: firebase.firestore.FieldValue.serverTimestamp(),
updated_at: firebase.firestore.FieldValue.serverTimestamp()
}
return new Promise((resolve, reject) => {
usersRef.add(user)
.then(ref => {
resolve(true)
})
.catch(error => {
console.error('An error occurred in addUser(): ', error)
reject(error)
})
})
},
...
// 以下を追記
uploadFile({ commit }, payload) {
const name = uuidv4()
return new Promise((resolve, reject) => {
firestorage.ref('images/' + name).put(payload.file)
.then(snapshot => {
snapshot.ref.getDownloadURL()
.then(url => {
resolve({ name, url })
})
})
.catch(error => {
console.error('An error occurred in uploadFile(): ', error)
reject(error)
})
})
}
...
}
uploadFile
アクションの追加と、addUser
アクションにavatar
フィールドの追加を行いました。
画像をFirebase Storageに保存し、そのURLをFirestoreに保存できるようになったので、最後にユーザー一覧画面に画像を表示するように修正しましょう。
pages/users/index.vue
に以下を追記します。
<template>
<div class="container mt-5">
<div class="row justify-content-center mb-3">
<div class="col-12 col-sm-6">
<h2>Users</h2>
</div>
</div>
<div class="row justify-content-center mb-3">
<!-- 以下を追記 -->
<div class="col-12 col-sm-1 font-weight-bold">Avatar</div>
<div class="col-12 col-sm-2 font-weight-bold">Name</div>
<div class="col-12 col-sm-1 font-weight-bold">Age</div>
<div class="col-12 col-sm-1 font-weight-bold">Edit</div>
<div class="col-12 col-sm-1 font-weight-bold">Delete</div>
</div>
<div v-for="(user, key) in $store.getters.getUsers" :key="key"
class="row justify-content-center align-items-center mb-3">
<!-- 以下を追記 -->
<div class="col-12 col-sm-1">
<img :src="user.avatar" class="img-fluid rounded-circle" />
</div>
...
</div>
</div>
</template>
<script>
// スクリプトは変更なし
</script>
いったん3人のユーザー情報をすべて消してから画像つきで再作成します。ユーザー一覧画面は以下のようになっているでしょうか。
まとめ
Firebase Storageに画像を保存する方法を解説しました。
長くなってしまったので変更/削除する方法は次の記事でまとめたいと思います。