7
votes

I am trying to use a google cloud function in Node.js to download a file for wordpress repo then send the file into a google cloud bucket. I have the wordpress file downloading but it fails to write to the google bucket.

function writeToBucket(jsonObject){

/*
 *  Google API authentication
 */

var gcs = require('@google-cloud/storage')({
         projectId: 'wp-media-cdn',
         keyFilename: 'wp-media-cdn-d9d7c61bfad9.json'
});

/*
 *  rename image file with image size, format: size X size imgName
 */

var pluginUrl = "https://downloads.wordpress.org/plugin/bbpress.2.5.14.zip";
    newPluginName = "bbpress";

/*
 *  Read image into stream, upload image to bucket
 */

var request = require('request');
var fs = require('fs'); //used for createWriteString()

var myBucket = gcs.bucket('test_buckyy'); //PUT BUCKET NAME HERE
var file = myBucket.file(nnewPluginName);

// file.exists() returns true if file already in bucket, then returns file url, exits function
if(file.exists()){
    return 'https://storage.googleapis.com/${test_buckyy}/${file}';
}

//pipes image data into fileStream
var fileStream = myBucket.file(newImageName).createWriteStream();
request(imgUrl).pipe(fileStream)
    .on('error', function(err) {
        console.log('upload failed');
    })
    .on('finish', function() {
        console.log('file uploaded');
    });
/*
 *  return image url
 *  use getSignedUrl
 */


    return 'https://storage.googleapis.com/${test_buckyy}/${file}';

}
2
Please, post errors messages. Look into log information.QuestionAndAnswer
Hello, did you ever find a solution? If so, could you add an answer?ThaDon
The only problem I can see is a typo of newPluginName here: var file = myBucket.file(nnewPluginName);ThaDon

2 Answers

6
votes

I just replicated your use case scenario and I successfully downloaded the file into the temporary folder of a Cloud Function and from there I copied this file into a bucket.

In order to achieve this, I downloaded the file using createWriteStream into the /tmp folder since is the only folder where we can store files in a Cloud Function, as stated in the Cloud Functions Execution Environment documentation.

After that, I just copied the file to a bucket following this Cloud Storage Uploading Objects documentation.

You can take a look of my sample function

Index.js

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

exports.writeToBucket = (req, res) => {
const http = require('http');
const fs = require('fs');

const file = fs.createWriteStream("/tmp/yourfile.jpg");
const request = http.get("YOUR_URL_TO_DOWNLOAD_A_FILE", function(response) {
  response.pipe(file);
});

console.log('file downloaded');

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();
const bucketName = 'YOUR_BUCKET_NAME';
const filename = '/tmp/yourfile.jpg';

// Uploads a local file to the bucket
storage.bucket(bucketName).upload(filename, {
  gzip: true,
  metadata: {
    cacheControl: 'no-cache',
  },
});

res.status(200).send(`${filename} uploaded to ${bucketName}.`);

};


package.json

{
  "name": "sample-http",
  "version": "0.0.1",
  "dependencies": {
        "@google-cloud/storage": "^3.0.3"
    }
}
3
votes

Using Chris32's answer I've created a similar version but avoiding the download of the image to the tmp folder. Hope it's useful !

'use strict';

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

exports.http = (request, response) => {
  const imageUrl = request.body.url;
  const fileName = imageUrl.substring(imageUrl.lastIndexOf('/') + 1);

  const storage = new Storage({keyFilename: "keyfile.json"});
  const bucket = storage.bucket('MY_BUCKET_NAME');
  const file = bucket.file(fileName);

  console.log('Uploading image')
  http.get(imageUrl, function(res) {
    res.pipe(
      file.createWriteStream({
        resumable: false,
        public: true,
        metadata: {
          contentType: res.headers["content-type"]
        }
      })
    );
  });

  console.log('Image uploaded')
  response.status(201).send('Image successful uploaded!');
};

exports.event = (event, callback) => {
  callback();
};