CLASSFUNC BLOG
We Share Our Knowledge
Upload files với Firebase Functions và Cloud Storage
Back-endCloudFunctions
Lê Thành
9 Th03 2022 05:56

firebaseFunctionsUploadFile.drawio.svg

1. Tạo 1 project functions

  • `firebase init functions` để kết nối với firebase project

Ảnh chụp Màn hình 2022-03-09 lúc 11.30.31.png

2. Sử dụng `busboy-firebase` để nhận files upload

const app = require('express')(); const bb = require('busboy-firebase'); const {functions, bucket} = require('../app'); const genId = require('cf-gen-id'); const {genDownloadUrlFromMetadata} = require( '../utils/genDownloadUrlFromMetadata'); const cors = require('cors'); app.use(cors()); app.post('/', bb, async (req, res) => { const downloadUrls = await Promise.all( //busboy-firebase xử lý với file nhận đc từ client và đưa vào req.files req.files?.map(async f => { const fname = f.originalname; const contents = f.buffer; await bucket.file(fname).save(contents); //lưu nội dung file // thêm metadata để có thể lấy link download từ storage const [meta] = await bucket.file(fname).setMetadata({ metadata: { firebaseStorageDownloadTokens: genId('token_', 20), }, }); //trả về link có thể download return genDownloadUrlFromMetadata(meta, fname); }), ); res.json({downloadUrls}); }); exports.upload = functions.https.onRequest(app);

Setting biến môi trường

CONSTANTS.js

const IS_CLI = process.env.IS_FIREBASE_CLI === 'true'; const STORAGE_EMULATOR_HOST = process.env.STORAGE_EMULATOR_HOST; const BUCKET_NAME = 'tên bucket trên firebase' // ví dụ `formzin-com.appspot.com` const FUNCTIONS_REGION = 'asia-southeast1'; //singpore module.exports = { IS_CLI, STORAGE_EMULATOR_HOST, BUCKET_NAME, FUNCTIONS_REGION, };

app.js

const {initializeApp} = require('firebase-admin/app'); const {getStorage} = require('firebase-admin/storage'); let functions = require('firebase-functions'); const {BUCKET_NAME, FUNCTIONS_REGION} = require('./CONSTANTS'); functions = functions.region(FUNCTIONS_REGION); const FB_CONFIG = JSON.parse(process.env.FIREBASE_CONFIG); const app = initializeApp({ ...FB_CONFIG, storageBucket: BUCKET_NAME, }); const storage = getStorage(app); const bucket = storage.bucket(); module.exports = exports = { app, storage, bucket, functions, };

genDownloadUrlFromMetadata.js

const {IS_CLI, STORAGE_EMULATOR_HOST, BUCKET_NAME} = require('../CONSTANTS'); const genDownloadUrlFromMetadata = (meta, fileName) => { const firebaseStorageDownloadTokens = meta?.metadata?.firebaseStorageDownloadTokens; let url; if (firebaseStorageDownloadTokens) { const domain = IS_CLI ? STORAGE_EMULATOR_HOST : 'https://firebasestorage.googleapis.com'; url = `${domain}/v0/b/${BUCKET_NAME}/o/${encodeURIComponent( fileName)}?alt=media&token=${firebaseStorageDownloadTokens}`; } else { url = meta?.mediaLink; } return url; }; exports.genDownloadUrlFromMetadata = genDownloadUrlFromMetadata;

Test local với firebase-emulators

firebase emulators:start --only functions,storage

Upload thử với Postman

Ảnh chụp Màn hình 2022-03-09 lúc 12.46.45.png

Deploy functions

firebase deploy --only functions:upload

Open to the world

  • Vào gcloud functions, thêm quyền allUser có thể invoke function `upload` vừa deploy

Ảnh chụp Màn hình 2022-03-09 lúc 12.51.27.png

Ảnh chụp Màn hình 2022-03-09 lúc 12.51.14.png

Test lại với Postman

Ảnh chụp Màn hình 2022-03-09 lúc 12.53.56.png


Done 🤗

Chúc các bạn thành công 🍻🍺