Firebase not upload correct images to Storage using Javascript

Viewed 159

I am working on a project that uses Firebase Realtime Database and Firebase Storage.

First Part:

I have a function to upload the Pictures of users in javascript:


const firebaseConfig = {
    apiKey: FB_WEB_API_KEY,
    authDomain: FB_WEB_AUTH_DOMAIN,
    databaseURL: FB_WEB_DATABASE_URL,
    projectId: FB_WEB_PROJECT_ID,
    storageBucket: FB_WEB_STORAGE_BUCKET,
    appId: FB_WEB_APP_ID,
}

firebase = require('firebase/app')
require('firebase/functions')
require('firebase/database')
require('firebase/storage')
require('firebase/auth')
require('firebase/functions')
firebase.initializeApp(firebaseConfig)


export async function setUserPicture(pId, userId, picture) {
    if (picture !== '' && picture != null) {
        let promises = []

        const filesRef = firebase.storage().ref(`users/${pId}/${userId}`)

        filesRef.listAll().then(async folder => {
            for (let file of folder.items) {
                promises.push(filesRef.child(file.name).delete())
            }

            // Wait until all previous images are deleted
            await Promise.all(promises)

            let attachmentRef = firebase
                .storage()
                .ref(`users/${pId}/${userId}/${userId}@${Date.now()}`)

            attachmentRef.put(picture).then(_ => {
                attachmentRef.getDownloadURL().then(url => {
                    firebase
                        .database()
                        .ref(`users/${pId}/${userId}`)
                        .update({ photoURL: url })
                })
            })
        })
    }
}

In this function all images related to user's avatars are uploaded to a folder called users in Firebase Storage following this pattern:

'users/${pId}/${userId}/'       // Inside this path is placed the images

Before upload the new image, I delete all previous images from the specific folder in the storage, to be sure that there are no previous images.

Also when I upload the image, I take the downloadURL and save it in a field of the User data.

This are the packages installed for this:

"firebase": "^7.12.0",
"firebase-admin": "^8.11.0",
"firebase-functions": "^3.6.1",

Second Part:

For this project, I have some Cloud Functions to handle some data. In this case, I have a cloud function to save 2 resized images in the Storage, in the same folders where I have the original image of the avatar. This is to use proper sizes to improve the load time.

const functions = require('firebase-functions')
const admin = require('firebase-admin')
const { tmpdir } = require('os')
const { dirname, join } = require('path')
const sharp = require('sharp')
const fs = require('fs-extra')
const { uuid } = require('uuidv4')

exports.onUploadUserPicture = functions
    .runWith({ memory: '2GB', timeoutSeconds: 120 })
    .storage.object()
    .onFinalize(async object => {
        const bucket = admin.storage().bucket()
        const originalPath = object.name
        const originalFileName = originalPath.split('/').pop()
        const userId = originalFileName.split('@').shift()
        const bucketDir = dirname(originalPath)

        const workingDir = join(tmpdir(), 'resizing')
        const tmpPath = join(workingDir, 'origin.png')

        const metadata = {
            contentDisposition: object.contentDisposition,
            contentEncoding: object.contentEncoding,
            contentLanguage: object.contentLanguage,
            contentType: object.contentType,
            metadata: object.metadata || {},
        }

        metadata.metadata.resizedImage = true

        console.log(`Apply resizing to ${originalFileName}`)

        if (!originalPath.includes('users') || !object.contentType.includes('image')) {
            console.log(`This file is not a user picture. Exit!`)
            return false
        } else if (originalFileName.includes('_50x50')) {
            console.log(`Already processed: [ ${originalFileName} ] for size: [ 50 ]. Exit!`)
            return false
        } else if (originalFileName.includes('_300x300')) {
            console.log(`Already processed: [ ${originalFileName} ] for size: [ 300 ]. Exit!`)
            return false
        }

        await fs.ensureDir(workingDir)
        await bucket.file(originalPath).download({ destination: tmpPath })

        const sizes = [50, 300]

        const promises = sizes.map(async size => {
            console.log(`Resizing ${originalFileName} at size ${size}`)

            const newImgName = `${userId}@${Date.now()}_${size}x${size}`
            const imgPath = join(workingDir, newImgName)
            await sharp(tmpPath)
                .clone()
                .resize(size, size, { fit: 'inside', withoutEnlargement: true })
                .toFile(imgPath)

            console.log(`Just resized ${newImgName} at size ${size}`)

            // If the original image has a download token, add a
            // new token to the image being resized
            if (object.metadata.firebaseStorageDownloadTokens) {
                metadata.metadata.firebaseStorageDownloadTokens = uuid()
            }

            return bucket.upload(imgPath, {
                destination: join(bucketDir, newImgName),
                metadata: metadata,
            })
        })

        await Promise.all(promises)
        return fs.remove(workingDir)
    })

In this Cloud Function, firstly, I verify if it is user picture (based on the location of the original image) and if it is not a resized image (not have a _50x50 or _300x300)

Then, I download the original image, create both resized thumbnails, and after that upload to Storage.

I apply some metadata from the original image, a convention name to be unique and also generate a new storage download token for each image,

The PROBLEM

The real issue is that when I verify in Firebase Storage, sometimes, in a random way, the picture uploaded or that appear in the Storage is not correct. Some times is a picture that I uploaded before and even that supposed to be deleted previously by one of these functions.

Is there something missing in these functions??

0 Answers
Related