roundrobin
roundrobin

Reputation: 716

Copy a file on firebase storage?

Is it possible to copy an existing file on firebase storage without needing to uploading it again?

I need it for a published/working version setup of my app.

Upvotes: 12

Views: 7797

Answers (5)

Mauro Russo
Mauro Russo

Reputation: 359

UPDATE

Now it's possible:

import { Storage } from '@google-cloud/storage'

const storage = new Storage({
    projectId: 'your-project-id',
    keyFilename: 'your-admin-keycert.json'
})

const copyResponse = await storage.bucket('your-bucket').file(`your-file`).copy(`new-destination`)

Upvotes: 1

Artur A
Artur A

Reputation: 9139

Firebase Storage clients support file copying inside the same bucket:

await bucketFileRef.copy('new-path/to/file');

Directly with Google Cloud Storage

Direct access is possible with @google-cloud/storage.

From firebase-admin

firebase-admin package, which should be used in a function backend, references @google-cloud/storage and can be used in a similar way.

Full example:

import { getStorage } from 'firebase-admin/storage';


const firebaseApp = initializeApp({
  storageBucket: 'YOUR-BUCKET-PATH',
});

const main = async() => {
  const bucket = getStorage(firebaseApp).bucket();

  const bucketFileRefToCopy = bucket.file('path/file-to-copy');

  // COPY
  await bucketFileRefToCopy.copy('new-path/to/file');
};


main();

Upvotes: 1

JuroOravec
JuroOravec

Reputation: 348

I needed to copy folders (including all it's descendants) in Google Cloud Storage. Here is the solution proposed by @vir-us, simplified and for NodeJS.

import type { Bucket } from '@google-cloud/storage';

/** Copy Cloud Storage resources from one folder to another. */
export const copyStorageFiles = async (input: {
  bucket: Bucket;
  fromFolder: string;
  toFolder: string;
  logger?: Console['info'];
}) => {
  const { bucket, fromFolder, toFolder, logger = console.info } = input;

  const [files] = await bucket.getFiles({ prefix: fromFolder });
  const promiseArray = files.map((file) => {
    const destination = file.name.replace(fromFolder, toFolder);
    logger("fileName = ", file.name, ", destination = ", destination);
    return file.copy(destination);
  });
  return Promise.all(promiseArray);
};

Upvotes: 3

vir us
vir us

Reputation: 10715

Here is an approach I ended up with for my project.

While it covers a broader case and copies all files under folder fromFolder to toFolder, it can be easily adopted to the case from the question (to copy only files one can pass delimiter = "/" - refer to the docs for more details)

const {Storage} = require('@google-cloud/storage');


module.exports = class StorageManager{

    constructor() {
        this.storage = new Storage();
        this.bucket = this.storage.bucket(<bucket-name-here>)
    }

    listFiles(prefix, delimiter){
        return this.bucket.getFiles({prefix, delimiter});
    }
    deleteFiles(prefix, delimiter){
        return this.bucket.deleteFiles({prefix, delimiter, force: true});
    }

    copyFilesInFolder(fromFolder, toFolder){
        return this.listFiles(fromFolder)
            .then(([files]) => {
                let promiseArray = files.map(file => {
                    let fileName = file.name
                    let destination = fileName.replace(fromFolder, toFolder)
                    console.log("fileName = ", fileName, ", destination = ", destination)
                    return file.copy(destination)
                })
                return Promise.all(promiseArray)
            })
    }
}

Upvotes: 5

Frank van Puffelen
Frank van Puffelen

Reputation: 599081

There is no method in the Firebase Storage API to make a copy of a file that you've already uploaded.

But Firebase Storage is built on top of Google Cloud Storage, which means that you can use the latter's API too. It looks like gsutil cp is what you're looking for. From the docs:

The gsutil cp command allows you to copy data between your local file system and the cloud, copy data within the cloud, and copy data between cloud storage providers.

Keep in mind that gsutil has full access to your storage bucket. So it is meant to be run on devices you fully trust (such as a server or your own development machine).

Upvotes: 10

Related Questions