Angular Firebase & Cloud Storage part 1
อยากเก็บรูปภาพใช่ไหม อยากเก็บไฟล์วีดีโอใช่ป่าว Firebase เขามีบริการอยู่นะ บริการนี้ชื่อ Cloud Storage
หลังจากใช้ Angular Firebase Library เขียนงานเชื่อมต่อระหว่าง front ที่เขียนด้วย Angular กับฐานข้อมูลอย่าง Firebase หนนี้เรามุ่งมาที่อีก featrue ซึ่งมีชื่อเรียกว่า Cloud Storage ครับ
Cloud Storage เก็บรูปภาพ เก็บไฟล์ เก็บวีดีโอ
ผมก็อยากให้งานออกมาเป็นชิ้นเป็นอันนะ ดังนั้นขอใช้โปรเจกต์เก่ามาเพิ่มหน้าใหม่ก็แล้วกัน ใครที่เพิ่งมาอ่านไม่รู้ว่าโปรเจกต์เก่าผมนั้นคืออะไรให้ดูด้านล่างนี้ ส่วนใครที่เขียน Angular พอเป็นอยู่แล้วก็ข้ามไปได้
เรามาเริ่มต้นกันเถอะ
CRETE NEW VIDEOS PAGE
จุดประสงค์คือ ผมชื่นชอบเกม Oxygen Not Included นี้มาก จึงดาวน์โหลดวีดีโอจาก Youtube มาเก็บไว้ที่เครื่องคอมฯตนเอง แต่แล้วครั้งนี้ผมกลับอยากเอามันไปเก็บไว้บน Cloud
และนี่คือหน้าตาเดิมๆของโปรเจกต์ ‘oxygen-not-included-wiki’ ที่ได้ทำไปแล้ว มันมีอยู่สองหน้าแต่ผมจะเพิ่มหน้าใหม่เข้าไป แบบนี้ครับ
หน้าใหม่ของผมอยู่ที่ไฟล์ app.component.html เพิ่มเลย
หลังจากนั้นไปวาง route ใหม่เพื่อให้ลิงก์ข้างต้นทำงานได้
เปิดไฟล์ app-routing.module.ts
{ path: 'cloudstorage/videos', component: CloudStorageVideosComponent },
มันจะยัง error อยู่เพราะคลาส CloudStorageVideosComponent ยังไม่ได้สร้าง
รออะไรล่ะ สร้างต่อเลย
ng g c components/cloud-storage-videos
เสร็จแล้วก็กลับไป import คลาสนี้ให้เรียบร้อย error นั่นก็จะหายไป
ลองคลิกมันสิ
นี่คืออ่านสด ทำสดเลยนะ ตายก็แก้ไขให้ดูแบบจ๊ะๆ ผมอ่านจากตรงนี้ ดูแล้วมันก็น่าจะง่ายๆ
สร้างปุ่ม upload ขึ้นมา (CSS ผมใช้ Bootstrap นะครับ)
เปิดไฟล์ cloud-storage-videos.component.html วาดๆ
<div class="container"> <div class="p-5"> <div class="form-group"> <label for="fileUpload">Video</label> <input type="file" class="form-control-file" id="fileUpload"> </div> </div></div>
ผลลัพธ์
กดปุ่ม Browse
ความจริงมันเลือก upload ทีละหลายไฟล์พร้อมกันได้นะ แต่ตอนนี้ลองแค่ไฟล์เดียวก่อน
เลือกมาสักไฟล์แล้วกด Open
:)
ทำต่อนะครับ เพิ่ม change event แก่ input tag
(change)="onFileUpload($event.target.files)"
จากนั้นเปิด cloud-storage-videos.component.ts เพื่อเขียนฟังก์ชันนี้
onFileUpload(files: FileList) { console.log(files);}
หัวใจก็คือ interface ชื่อ FileList จำต้องได้รายการไฟล์ที่เลือก
ลองเลือกใหม่อีกที
ดูดีมากเลยครับ
เข้าเรื่อง Cloud Storage ได้แล้ว
:)
DO UPLOAD FILE (Single File)
ลงทะเบียน AngularFireStorageModule ก่อนเลย
เปิดไฟล์ app.module.ts
import { AngularFireStorageModule } from '@angular/fire/storage';
และ
imports: [ ... AngularFireStorageModule, ...],
กลับไปที่ cloud-storage-videos.component.ts
เอามันเข้ามาที่ constructor
constructor( private storage: AngularFireStorage,) { }
โปรดสังเกตตอน import ด้วยว่า path มันถูกต้องหรือไม่
import { AngularFireStorage } from '@angular/fire/storage/storage';
จากข้างต้น ผมใช้ VS Code จะเห็นได้ว่าคำว่า storage เกินมา ให้ลบออกนะ
หากใครยัง error ก็ให้หยุด server แล้ว ng s
ใหม่
ปัง error อีก
ให้ import ‘firebase/storage’ เพิ่มที่ AppModule
...import 'firebase/database';import 'firebase/firestore';import 'firebase/storage';...
เสร็จแล้วมาเขียนฟังก์ชัน onFileUpload อีกหน่อย
onFileUpload(files: FileList) { const file = files[0]; // get single file const path = `videos/${file.name}`; this.storage.upload(path, file);}
ผมตั้งใจให้เก็บไว้ที่ path ชื่อ videos ตามด้วย / ชื่อไฟล์
ไม่รู้ได้ไหมนะ ลองไป upload file video นี้กันเลย
ปังเจอ 403 forbidden คือ Firebase มันรู้แล้วว่าเป็นเรา แต่พื้นที่ที่เราต้องการใช้งานยังไม่ได้รับอนุญาต ดังนั้นไปที่โปรเจกต์บน Firebase
…
มองไปทางซ้ายเลือก storage
มันบอกว่าเฉพาะ user ที่ได้ผ่านการ authenticated แล้วเท่านั้นจึงใช้ได้ …เดี๋ยวเราแก้ให้เป็นใคร upload ก็ได้ ไว้เราทำเรื่อง authentication เป็นแล้วค่อยแก้กลับ
เขาบอกว่าพื้นที่ที่จะใช้เก็บไฟล์อยู่ที่นี่ (ถ้าได้เลือกไว้แต่แรก ถ้าไม่ได้เลือกก็เลือกเสีย) ระยะทางมีผลต่อความเร็วนะครับ ยิ่งไกลยิ่งช้า
สิ่งนี้เรียกว่า Cloud Storage bucket
ผมได้เลือกไว้แล้วชื่อ asia-south1 (แถวๆอินเดีย)
จากนั้นเลือก Rules เพราะต้องการเปลี่ยนกฏให้ใครก็ได้ (ไม่ต้อง sign in) สามารถใช้ได้หมด (ไม่ค่อยปลอดภัยนะบอกเลย)
ตรง allow read, write: if request.auth != null;
แก้ไขให้เป็น null ได้ โดยเปลี่ยนจากเครื่องหมาย !=
แก้เป็น ==
เสร็จแล้วกดปุ่ม Publish
ขอเพิ่มโค้ดฟังก์ชัน onFileUpload อีกครับ
onFileUpload(files: FileList) { const file = files[0]; // get single file const path = `videos/${file.name}`; this.uploadPercentage$ = this.storage.upload(path, file).percentageChanges();}
คืออยากเห็น % มันวิ่งว่าคืบหน้าถึงไหนแล้ว
ประกาศตัวแปร uploadPercentage$
uploadPercentage$: Observable<number>;
กลับไปที่ .html แล้วแต่งเติม
<div *ngIf="uploadPercentage$ | async as percentage"> <div>uploading {{percentage}}%</div></div>
ลอง!
ผล
กลับไปดูที่ Firebase Cloud Storage ครับ
refresh สักหน
กดตรง videos เข้าไปดูซิ
ยิ้มเลยสินะ
part ถัดไปเราจะเรียกรายการไฟล์ที่ถูก upload ทั้งหมดมาแสดง
ไว้เจอกัน!
อ่านต่อ part 2