記事の目的
Firebase便利ですよね。
なかでも簡単にファイルアップロードは便利です。
こちらに手順を記載されている記事があります
https://qiita.com/daikiojm/items/1c5940d618b3b644439a
- downloadUrlが非推奨になっていること
- キャッシュの設定とか
- 権限を少し
の追記だけしておきます。
早速コードの箇所だけ
Material Designを利用していますが、使わなくても大丈夫です。
(ボタンをおしゃれにするために、inputフィールドを隠しています。)
<!-- テキストファイルを選択するinput -->
<div id="input-area">
<input #fileUpload hidden type="file" value=""
(change)="selectFile($event)"/>
<button
(click)="fileUpload.click()"
type="button"
mat-button color="primary">ファイル選択
</button>
<p *ngIf="selectedFile">アップロードファイル: {{selectedFile.name}}</p>
<button [disabled]="!selectedFile"
mat-stroked-button color="primary"
(click)="upload();">Upload
</button>
</div>
<!-- アップロードしたファイルを表示するエリア -->
<a *ngIf="uploadFileUrl" [href]="uploadFileUrl">{{ uploadFileUrl }}</a>
// selected file
public selectedFile;
// ファイルのURL
public uploadFileUrl;
constructor(
private storage: AngularFireStorage,
private store: AngularFirestore,
) {
}
selectFile(evt: any) {
// ファイルを未選択で閉じた場合など。
if (!evt.target || !evt.target.files || evt.target.files.length !== 1) {
this.selectedFile = null;
return;
}
this.selectedFile = evt.target.files[0];
}
async upload() {
if (!this.selectedFile) {
return;
}
// ファイルをUIDごとに分けるとか
const filePath = 'uploads/' + 'uid等でフォルダを分ける' + '/' + this.selectedFile.name;
// ストレージの参照をもつ
const storageRef = this.storage.ref(filePath);
// putまたはputStringであげる
const result = await storageRef.put(this.selectedFile, {'cacheControl': 'public, max-age=86400'});
console.log(result);
// storageの参照からダウンロードURLを取得(先の例にあったようにobservableのまま受け取ってもOK)
storageRef.getDownloadURL().subscribe((result) => {
this.uploadFileUrl = result;
// ここでStoreにユーザがアップロードしたファイル一覧に保持とか
});
}
ほぼ同じ方法で
blobやbase64もできます。
https://firebase.google.com/docs/storage/web/upload-files?hl=ja
const result = await storageRef.put(this.selectedFile, {'cacheControl': 'public, max-age=86400'});
ここで例えばキャッシュをもたせる場合は、
上記のように、putのオプションとして設定可能です。
FirebaseStorageの権限について
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read;
}
match /uploads/{allPaths=**} {
allow read;
allow create: if request.auth != null && request.resource.size <= 10 * 1024 * 1024;
allow update: if request.auth.uid == resource.data.uid && request.resource.size <= 10 * 1024 * 1024;
allow delete: if request.auth.uid == resource.data.uid;
}
}
}
match /{allPaths=**} {
allow read;
}
最初に任意のパスへの書き込みは規制した方が良いかと思います。
match /uploads/{allPaths=**} {
allow read;
allow create: if request.auth != null && request.resource.size <= 10 * 1024 * 1024;
allow update: if request.auth.uid == resource.data.uid && request.resource.size <= 10 * 1024 * 1024;
allow delete: if request.auth.uid == resource.data.uid;
}
続いて、uploads配下(ここは利用したいパスによります)に関しての権限を決めます。
例として、プロフィール画像のアップロードの場合、
- read: 読み込みは誰でもOK → if はなければ常にTrue扱い
- create: 認証済みユーザなら登録可なので、request.authがnullじゃないこと=認証済みユーザであること
を確認(firebase authenticationを利用して下さい) - update: データを登録したユーザと変更者のUIDが一致していたら変更可とする(firebase authenticationを利用して下さい)
- delete: データを登録したユーザと削除者のUIDが一致していたら削除可とする(firebase authenticationを利用して下さい)
追加で、createとuploadの際に10MB以下としてあります。
(大きいファイルをがんがん上げられるのを防ぐため)
雑ですいません。
Angular最高!!
詳細は以下に有ります。
https://github.com/angular/angularfire/blob/master/docs/storage/storage.md
あと使いそうなところだと
// observe percentage changes
this.uploadPercent = task.percentageChanges();
// get notified when the download URL is available
task.snapshotChanges().pipe(
finalize(() => this.downloadURL = fileRef.getDownloadURL() )
)
.subscribe()
ここの箇所でUpload時のプログラスバーを出したいときなど便利です。