0

When trying to access an image in my home directory of Firebase storage with node.js functions, I'm getting [object Object] as a response. I guess I initialized the bucket incorrectly, but not sure where I'm going wrong.

That's the debug info in firebase functions:

ChildProcessError: `composite -compose Dst_Out [object Object] [object Object] /tmp/output_final2.png` failed with code 1

Here's my code:

const admin = require('firebase-admin');
admin.initializeApp();
const storage = admin.storage();


const os = require('os');
const path = require('path');
const spawn = require('child-process-promise').spawn;


exports.onFileChange= functions.storage.object().onFinalize(async object => {

    const bucket = storage.bucket('myID.appspot.com/');
    const contentType = object.contentType;
    const filePath = object.name;
    console.log('File change detected, function execution started');

    if (object.resourceState === 'not_exists') {
        console.log('We deleted a file, exit...');
        return;
    }

    if (path.basename(filePath).startsWith('changed-')) {
        console.log('We already changed that file!');
        return;
    }

    const destBucket = bucket;
    const tmpFilePath = path.join(os.tmpdir(), path.basename(filePath));
    const border = bucket.file("border.png");
    const mask1 = bucket.file("mask1.png");
    const metadata = { contentType: contentType };
    return destBucket.file(filePath).download({
        destination: tmpFilePath
    }).then(() => {
        return spawn('composite', ['-compose', 'Dst_Out', mask1, border, tmpFilePath]);

    }).then(() => {
        return destBucket.upload(tmpFilePath, {
            destination: 'changed-' + path.basename(filePath),
            metadata: metadata
        })
    }); });```


6
  • With const bucket = storage.bucket('myID.appspot.com/');are you declaring your default bucket? Commented Jan 15, 2020 at 10:57
  • yes, declaring with const bucket = storage.bucket(); doesn't solve the problem Commented Jan 15, 2020 at 12:24
  • @RenaudTarnec I guess there is something wrong with accessing the file with const border = bucket.file("border.png");? Commented Jan 15, 2020 at 12:28
  • Can you add a picture of your bucket, showing the border.png file? Commented Jan 15, 2020 at 12:29
  • @RenaudTarnec i.sstatic.net/1a6DQ.jpg Commented Jan 15, 2020 at 12:35

2 Answers 2

1

If, with

const bucket = storage.bucket('myID.appspot.com/');

your goal is to initialize the default bucket, you should just do

const bucket = storage.bucket();

since you have declared storage as admin.storage()


UPDATE (following your comment about const border = bucket.file("border.png");)

In addition, by looking at the code of a similar Cloud Function (from the official samples, using ImageMagick and spawn) it appears that you should not pass to the spawn() method some File objects created through the file() method of the Cloud Storage Node.js Client API (i.e. const border = bucket.file("border.png");) but some files that you have previously saved to a temp directory.

Look at the following excerpt from the Cloud Function example referred to above. They define some temporary directory and file paths (using the path module), download the files to this directory and use them to call the spawn() method.

  //....
  const filePath = object.name;
  const contentType = object.contentType; // This is the image MIME type
  const fileDir = path.dirname(filePath);
  const fileName = path.basename(filePath);
  const thumbFilePath = path.normalize(path.join(fileDir, `${THUMB_PREFIX}${fileName}`));   // <---------
  const tempLocalFile = path.join(os.tmpdir(), filePath);    // <---------
  const tempLocalDir = path.dirname(tempLocalFile);     // <---------
  const tempLocalThumbFile = path.join(os.tmpdir(), thumbFilePath);     // <---------

  //....

  // Cloud Storage files.
  const bucket = admin.storage().bucket(object.bucket);
  const file = bucket.file(filePath);
  const thumbFile = bucket.file(thumbFilePath);
  const metadata = {
    contentType: contentType,
    // To enable Client-side caching you can set the Cache-Control headers here. Uncomment below.
    // 'Cache-Control': 'public,max-age=3600',
  };

  // Create the temp directory where the storage file will be downloaded.
  await mkdirp(tempLocalDir)   // <---------
  // Download file from bucket.
  await file.download({destination: tempLocalFile});    // <---------
  console.log('The file has been downloaded to', tempLocalFile);
  // Generate a thumbnail using ImageMagick.
  await spawn('convert', [tempLocalFile, '-thumbnail', `${THUMB_MAX_WIDTH}x${THUMB_MAX_HEIGHT}>`, tempLocalThumbFile], {capture: ['stdout', 'stderr']});   
  //.....
Sign up to request clarification or add additional context in comments.

2 Comments

thanks, tried it but I'm still getting [object Object] [object Object]
Thanks a lot, this solved the issue with working with files in storage. Additionally I figured out that "composite" can't be used with firebase functions; apparently it's only working with "convert". Still having some issues here but not related to the primary question.
0

You can't pass Cloud Storage File type objects to spawn. You need to pass strings that will be used to create the command line. This means you need to download those files locally to /tmp before you can work with them - ImageMagick doesn't know how to work file in Cloud Storage.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.