Vue を使ってFirebaseのストレージにファイルを保存する
Vue を使ってFirebaseのストレージにファイルを保存する
2022年4月17日
Vue を使って Firebase のストレージにファイルを保存する
前回の記事では、Vue でページ毎にアクセスの権限を使い分けるやり方を紹介しました。今回は、前回の実装を少し発展させて、「管理者モード」を考えてみます。この記事では、Firebase のストレージに管理者としてファイルをアップロードする方法を紹介します。
前回の記事では、Vue でページ毎にアクセスの権限を使い分けるやり方を紹介しました。今回は、前回の実装を少し発展させて、「管理者モード」を考えてみます。この記事では、Firebase のストレージに管理者としてファイルをアップロードする方法を紹介します。
管理者モードの利用例
まずは、管理者モードで何をするかの例を紹介します。 例えば、ブログサービスを提供する事を考えた場合には、ブログの記事を投稿する機能と、投稿された記事を閲覧する機能が必要になります。
この場合、ブログの記事を投稿するのは基本的にブログサービスの「管理者」が投稿するという形になります。
この場合、管理者は「特定の利用者」になって、閲覧者(一般の利用者)は、それ以外の利用者というように分ける事ができます。
この記事では、まずは、ファイルをインターネットのサーバーに保存する方法を紹介します。
まずは、管理者モードで何をするかの例を紹介します。 例えば、ブログサービスを提供する事を考えた場合には、ブログの記事を投稿する機能と、投稿された記事を閲覧する機能が必要になります。
この場合、ブログの記事を投稿するのは基本的にブログサービスの「管理者」が投稿するという形になります。
この場合、管理者は「特定の利用者」になって、閲覧者(一般の利用者)は、それ以外の利用者というように分ける事ができます。
この記事では、まずは、ファイルをインターネットのサーバーに保存する方法を紹介します。
Firebase のストレージ機能を使う
インターネットにファイルを保存するには、「保存する場所」が必要になります。今回は、この場所として Firebase のストレージ機能を利用する事にします。
前回までに、Firebase のプロジェクトを作成しているので今回は Firebase のストレージ機能を新たに有効にします。これは、Firebase コンソールから可能です。最初はインターネット上に公開せずにテストするので、「テストモード」を選択すれば、当面はセキュリティールールを設定しないでも基本的なテストが可能になります。
テストモードで設定されるセキュリティルールです。この例では、2022 年の 5 月 17 日までは、「誰でも読み書き可能」というルールです。
したがって、このままインターネットで公開した場合、Firebase のプロジェクト情報があれば、誰でもストレージのデータを操作できるようになっているため、セキュリティ上の問題があります。したがって、インターネットに公開する前にセキュリティルールの正しい設定が必要になります。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if
request.time < timestamp.date(2022, 5, 17);
}
}
}
プロダクションモードを選択した場合は、基本的なアクセスは読み書きともに禁止されているので、必要に応じてアクセスを許可するためのルール設定をしないと Firebase のストレージ機能を利用する事はできません。
インターネットにファイルを保存するには、「保存する場所」が必要になります。今回は、この場所として Firebase のストレージ機能を利用する事にします。
前回までに、Firebase のプロジェクトを作成しているので今回は Firebase のストレージ機能を新たに有効にします。これは、Firebase コンソールから可能です。最初はインターネット上に公開せずにテストするので、「テストモード」を選択すれば、当面はセキュリティールールを設定しないでも基本的なテストが可能になります。
テストモードで設定されるセキュリティルールです。この例では、2022 年の 5 月 17 日までは、「誰でも読み書き可能」というルールです。
したがって、このままインターネットで公開した場合、Firebase のプロジェクト情報があれば、誰でもストレージのデータを操作できるようになっているため、セキュリティ上の問題があります。したがって、インターネットに公開する前にセキュリティルールの正しい設定が必要になります。
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if
request.time < timestamp.date(2022, 5, 17);
}
}
}
プロダクションモードを選択した場合は、基本的なアクセスは読み書きともに禁止されているので、必要に応じてアクセスを許可するためのルール設定をしないと Firebase のストレージ機能を利用する事はできません。
アップロードフォームを作成する
まずは、 Vue でファイルをアップロードするためのフォーム(部品)を作成します。
<template>
<div>
<div>
<label>ファイル</label>
<input
class="form-control"
type="text"
v-model="filename"
placeholder="ファイルが選択されていません"
readonly
/>
<input
class="hidden"
ref="file_input"
type="file"
@change="file_selected"
/>
<button class="btn btn-primary" @click="$refs.file_input.click()">
アップロード
</button>
</div>
</div>
</template>
<script>
import { uploadFile } from "../lib/firebase";
export default {
data() {
return {
filename: "",
};
},
methods: {
file_selected(e) {
const file = e.target.files[0];
this.filename = file.name;
uploadFile("sample/" + file.name, file).then((url) => {
if (url) {
console.log(url);
} else {
console.log("Upload error");
}
});
},
},
};
</script>
<style scoped>
.hidden {
display: none;
}
</style>
ファイルの選択には「input」のタグで、「type="file"」と指定する事もできますが、表記が英語になっているので、少し工夫をして通常の「input」のタグで、選択したファイル名を表示できるようにています。「input type="file"」の部分は、CSS の記述で表示されないようにしています。
ファイルが選択された時点でファイルをアップロードする処理を別に用意して置いて呼び出すようにしています。あとは、このフォームの部品を呼び出して表示できるようにしておけば良いだけです。
今回は、前回作成した、ログインが必要なページの「AboutView.vue」を変更して、「AdminView.vue」に変更して、表示のためのパスも、「/about」から、「/admin」に変更しています。
変更点は
- ファイル名の変更( src/views/AboutView.vueから src/views/AdminView.vue)
- src/router/index.jsの変更
- src/App.vueの変更
基本的に、「About や about」の部分を「Admin や admin」に書き換えます。
まずは、 Vue でファイルをアップロードするためのフォーム(部品)を作成します。
<template>
<div>
<div>
<label>ファイル</label>
<input
class="form-control"
type="text"
v-model="filename"
placeholder="ファイルが選択されていません"
readonly
/>
<input
class="hidden"
ref="file_input"
type="file"
@change="file_selected"
/>
<button class="btn btn-primary" @click="$refs.file_input.click()">
アップロード
</button>
</div>
</div>
</template>
<script>
import { uploadFile } from "../lib/firebase";
export default {
data() {
return {
filename: "",
};
},
methods: {
file_selected(e) {
const file = e.target.files[0];
this.filename = file.name;
uploadFile("sample/" + file.name, file).then((url) => {
if (url) {
console.log(url);
} else {
console.log("Upload error");
}
});
},
},
};
</script>
<style scoped>
.hidden {
display: none;
}
</style>
ファイルの選択には「input」のタグで、「type="file"」と指定する事もできますが、表記が英語になっているので、少し工夫をして通常の「input」のタグで、選択したファイル名を表示できるようにています。「input type="file"」の部分は、CSS の記述で表示されないようにしています。
ファイルが選択された時点でファイルをアップロードする処理を別に用意して置いて呼び出すようにしています。あとは、このフォームの部品を呼び出して表示できるようにしておけば良いだけです。
今回は、前回作成した、ログインが必要なページの「AboutView.vue」を変更して、「AdminView.vue」に変更して、表示のためのパスも、「/about」から、「/admin」に変更しています。
変更点は
- ファイル名の変更( src/views/AboutView.vueから src/views/AdminView.vue)
- src/router/index.jsの変更
- src/App.vueの変更
基本的に、「About や about」の部分を「Admin や admin」に書き換えます。
Firebase の処理の追加
前回は、Firebase の初期化のために、 src/lib/firebase.jsを作成していますが、今回はこのファイルに、ファイルをアップロードするための処理を追加します。
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import {
getDownloadURL,
getStorage,
ref,
uploadBytesResumable,
} from "firebase/storage";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
....
// Initialize Firebase
export const firebase = initializeApp(firebaseConfig);
export const auth = getAuth();
export const storage = getStorage();
export function uploadFile(path, file) {
return new Promise((resolve) => {
const fileRef = ref(storage, path);
const uploadTask = uploadBytesResumable(fileRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
// Current completion in a percentage of the total transfer
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is ", progress + " % done.");
switch (snapshot.state) {
case "paused":
console.log("Upload is paused.");
break;
case "running":
console.log("Upload is running.");
break;
}
},
(error) => {
// Error -- Handle unsuccessful uploads
resolve(undefined);
},
() => {
// Handle successful uploads on complete
// --> Gets the download URL
getDownloadURL(uploadTask.snapshot.ref)
.then((downloadURL) => {
resolve(downloadURL);
})
.catch((error) => {
resolve(undefined);
});
}
);
});
}
Firebase のストレージを使うためのオブジェクトを作成して、ファイルをアップロードして、ファイルにアクセスするための URL を返すようになっています。ファイルのアップロードが失敗した場合は、URL の代わりにundefinedを返すようにしています。
あとは、「src/views/AdminView.vue」から、アップロードフォームの部品を呼び出せば完了です。
<template>
<div v-if="login.loginState" class="admin">
<h1>This is an about page</h1>
<UploadForm />
</div>
<div v-if="!login.loginState">
<LoginForm />
</div>
</template>
<script>
import { useLoginStore } from "../stores/login";
import LoginForm from "../components/loginForm.vue";
import UploadForm from "../components/uploadForm.vue";
export default {
components: { LoginForm, UploadForm },
setup() {
const login = useLoginStore();
return {
login,
};
},
data() {
return {
loginInfo: {
email: "",
password: "",
},
};
},
};
</script>
<style>
@media (min-width: 1024px) {
.admin {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
これでログインしていない場合には、アップロードフォームは表示されないので、アップロードする事はできません。
前回は、Firebase の初期化のために、 src/lib/firebase.jsを作成していますが、今回はこのファイルに、ファイルをアップロードするための処理を追加します。
// Import the functions you need from the SDKs you need
import { initializeApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import {
getDownloadURL,
getStorage,
ref,
uploadBytesResumable,
} from "firebase/storage";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries
....
// Initialize Firebase
export const firebase = initializeApp(firebaseConfig);
export const auth = getAuth();
export const storage = getStorage();
export function uploadFile(path, file) {
return new Promise((resolve) => {
const fileRef = ref(storage, path);
const uploadTask = uploadBytesResumable(fileRef, file);
uploadTask.on(
"state_changed",
(snapshot) => {
// Current completion in a percentage of the total transfer
const progress =
(snapshot.bytesTransferred / snapshot.totalBytes) * 100;
console.log("Upload is ", progress + " % done.");
switch (snapshot.state) {
case "paused":
console.log("Upload is paused.");
break;
case "running":
console.log("Upload is running.");
break;
}
},
(error) => {
// Error -- Handle unsuccessful uploads
resolve(undefined);
},
() => {
// Handle successful uploads on complete
// --> Gets the download URL
getDownloadURL(uploadTask.snapshot.ref)
.then((downloadURL) => {
resolve(downloadURL);
})
.catch((error) => {
resolve(undefined);
});
}
);
});
}
Firebase のストレージを使うためのオブジェクトを作成して、ファイルをアップロードして、ファイルにアクセスするための URL を返すようになっています。ファイルのアップロードが失敗した場合は、URL の代わりにundefinedを返すようにしています。
あとは、「src/views/AdminView.vue」から、アップロードフォームの部品を呼び出せば完了です。
<template>
<div v-if="login.loginState" class="admin">
<h1>This is an about page</h1>
<UploadForm />
</div>
<div v-if="!login.loginState">
<LoginForm />
</div>
</template>
<script>
import { useLoginStore } from "../stores/login";
import LoginForm from "../components/loginForm.vue";
import UploadForm from "../components/uploadForm.vue";
export default {
components: { LoginForm, UploadForm },
setup() {
const login = useLoginStore();
return {
login,
};
},
data() {
return {
loginInfo: {
email: "",
password: "",
},
};
},
};
</script>
<style>
@media (min-width: 1024px) {
.admin {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
これでログインしていない場合には、アップロードフォームは表示されないので、アップロードする事はできません。
まとめ
今回は、Vue を利用した本格的なサービスを作成する第一段階として、Firebase のストレージ機能を利用して、インターネット上にファイルをアップロードして保存する機能の実装のやり方を紹介しました。
実際にファイルを Firebase のストレージにアップロードできるのはログインしたユーザーだけにしています。Firebase を利用すると、初心者でも、Firebase の機能を呼び出すだけで、こうした機能も簡単に実現できます。
次回は、アップロードして保存したファイルの一覧を表示する方法を紹介します。
今回は、Vue を利用した本格的なサービスを作成する第一段階として、Firebase のストレージ機能を利用して、インターネット上にファイルをアップロードして保存する機能の実装のやり方を紹介しました。
実際にファイルを Firebase のストレージにアップロードできるのはログインしたユーザーだけにしています。Firebase を利用すると、初心者でも、Firebase の機能を呼び出すだけで、こうした機能も簡単に実現できます。
次回は、アップロードして保存したファイルの一覧を表示する方法を紹介します。
コメント
コメントを投稿