7

Can we upload empty folders or simply folders who contains many files in it on the firebase storage ?

Because actually i can upload one files but too, multiples files, but i didn't find how to do it with folders.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Zahreddine Laidi
  • 560
  • 1
  • 7
  • 20

3 Answers3

15

I'd suggest you to go to Google Cloud (Firebase projects live in the Google Cloud as well), and check your storage buckets there. You'll be able to see an upload folder option there, which you can use to upload folders through a GUI. You can drag and drop multiple folders if you wish.

2

There is no way to upload an entire folder to Cloud Storage for Firebase in one go. You will have to upload the individual files in the folder.

The is no concept of an empty folder in Cloud Storage for Firebase. Folders only exist by the fact that they have files in them.

Also see:

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the answer. – Zahreddine Laidi Oct 03 '18 at 13:43
  • But can we create a kind of documents folders upload, like, we retrieve the folders with an drag and drop (because i use a drag and drop..), we take the name of the folder, and all of the files in it, and we simply create a folders in firebase storage with the name of the folder, and we store all of the files in the folders in the firebase storage with the multiple file upload. Can it works or not ?? @FrankvanPuffelen – Zahreddine Laidi Oct 03 '18 at 15:02
  • I don't think you get a list of files in a folder in JavaScript, as that would be a security risk. But if the user drops multiple files, you can loop through those, upload them, including recreating part of the folder structure. It's a multi-step use-case, but definitely possible. If you're having problems implementing it, show precisely at what step you are stuck. See [how to create a minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) to have the best chance that someone can help. – Frank van Puffelen Oct 03 '18 at 15:38
2

To do this programmatically, the best solution is to:

(1) Recursively get a list of all the files in the folder you wish to upload

(2) Upload all files in one hit with Promise.all

This approach works because, inter alia, firebase creates missing storage paths for you

The code (written in TS) for (1) and (2) follows

RECURSIVELY GET A LIST OF FILES

import { Dirent, readdirSync } from 'fs'
import path from 'path'
import { IPath } from '../interfaces/i-path'
import { escapeRegExp } from 'lodash'

interface IDirent {
  dirent: Dirent
  path: string
}

const getAllFiles = (dir: string): IDirent[] => {

  const dirents: IDirent[] = readdirSync(dir, { withFileTypes: true }).map((dirent: Dirent) => ({ dirent, path: path.resolve(dir, dirent.name) }))

  return dirents.reduce((acc: IDirent[], dirent: IDirent) => {
    if (dirent.dirent.isDirectory()) return [...acc, ...getAllFiles(dirent.path)]
    if (dirent.dirent.isFile()) return [...acc, dirent]
    return acc
  }, [])
}

export const getAllFilesInFolder = (dir: string): IPath[] => {

  const regex = new RegExp(`^${escapeRegExp(dir)}`)

  return getAllFiles(dir).map((dirent: IDirent) => {
    let shortPosixPath: string = dirent.path.replace(regex, '')
    shortPosixPath = shortPosixPath.split(path.sep).join(path.posix.sep)
    if (shortPosixPath.startsWith(path.posix.sep)) shortPosixPath = shortPosixPath.substring(1)
    return { fullPath: dirent.path, shortPosixPath }
  })
}

UPLOAD ALL FILES IN ONE HIT

import os from 'os'
import { getAllFilesInFolder } from '../../utils/get-all-files-in-folder'
import { IPath } from '../../interfaces/i-path'
import admin from 'firebase-admin'
import { getObjectPath } from '../../utils/string-utils'
import path from 'path'
import * as functions from 'firebase-functions'

// the following code will live inside some function

const storageBasePath = 'videos-out/test-videos/video-14/hls'

const dir: string = '/temp/my-folder-to-upload'
const files: IPath[] = getAllFilesInFolder(dir)

// object.bucket is just a string and is the bucket you are uploading to - e.g. something.appspot.com
const promises = files.map((file: IPath) => {
  const destination = `${storageBasePath}/${file.shortPosixPath}`
  return admin.storage().bucket(object.bucket).upload(file.fullPath, { destination })
})

Promise.all(promises).then(
  () => console.log('success')
).catch(
  () => console.log('failure')
)

Finally, the interface IPath is simple

export interface IPath {
  fullPath: string
  shortPosixPath: string
}
danday74
  • 52,471
  • 49
  • 232
  • 283