在数据库触发的云功能上获取Firebase存储对象

时间:2017-08-08 10:15:52

标签: firebase firebase-storage google-cloud-functions

我想在将记录添加到数据库时生成拇指图像。 在Firebase网站上,他们有一些示例,但它们都基于存储触发器而不是数据库触发器:

图像数据库对象:

image: {
  name: abc123,
  raw: download url abc123 
}

-

firebase thumb generator示例(已触发存储):

exports.generateThumbnail = functions.storage.object().onChange(event => {
  const object = event.data; // The Storage object.

  const fileBucket = object.bucket; // The Storage bucket that contains the file.
  const filePath = object.name; // File path in the bucket.
  const contentType = object.contentType; // File content type.
  const resourceState = object.resourceState; // The resourceState is 'exists' or 'not_exists' (for file/folder deletions).
  const metageneration = object.metageneration; // Number of times metadata has been generated. New objects have a value of 1.

  // Exit if this is triggered on a file that is not an image.
  if (!contentType.startsWith('image/')) {
    console.log('This is not an image.');
    return;
  }

  // Get the file name.
  const fileName = path.basename(filePath);
  // Exit if the image is already a thumbnail.
  if (fileName.startsWith('thumb_')) {
    console.log('Already a Thumbnail.');
    return;
  }

  // Exit if this is a move or deletion event.
  if (resourceState === 'not_exists') {
    console.log('This is a deletion event.');
    return;
  }

  // Exit if file exists but is not new and is only being triggered
  // because of a metadata change.
  if (resourceState === 'exists' && metageneration > 1) {
    console.log('This is a metadata change event.');
    return;
  }

  // Download file from bucket.
  const bucket = gcs.bucket(fileBucket);

  const metadata = {
    contentType: contentType
  };
  // We add a 'thumb_' prefix to thumbnails file name. That's where we'll upload the thumbnail.
  const thumbFileName = `thumb_${fileName}`;
  const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
  // Create write stream for uploading thumbnail
  const thumbnailUploadStream = bucket.file(thumbFilePath).createWriteStream({metadata});

  // Create Sharp pipeline for resizing the image and use pipe to read from bucket read stream
  const pipeline = sharp();
  pipeline
    .resize(THUMB_MAX_WIDTH, THUMB_MAX_HEIGHT)
    .max()
    .pipe(thumbnailUploadStream);

  bucket.file(filePath).createReadStream().pipe(pipeline);

  const streamAsPromise = new Promise((resolve, reject) =>
    thumbnailUploadStream.on('finish', resolve).on('error', reject));
  return streamAsPromise.then(() => {
    console.log('Thumbnail created successfully');
  });
});

-

我希望它如何工作(数据库触发):

数据库触发器事件没有存储对象。如何访问存储对象? 成功创建缩略图后,我想将拇指图像的donwloadUrl添加到数据库

exports.generateThumbnail = functions.database.ref('/data/{dataID}/childData/{childDataID}/image/name').onCreate(event => {

      const object = event.data; // This Storage object does not work when using a database trigger so how do I access the same storage object, I have the image name?

      //thumb generator code...

      return streamAsPromise.then(() => {
        console.log('Thumbnail created successfully');
        //add thumb image download url back to the database
      });
    });

-

image: {
  name: abc123,
  raw: download url abc123
  thumb: download url thumb_abc123  //added after thumb is created
}

1 个答案:

答案 0 :(得分:2)

这就是我开始工作的方式。

将云存储添加到您的项目中 如果您想像我一样检索已签名的图像,请将projectId和keyFilename添加到云存储参考

const gcs = require('@google-cloud/storage')({
  projectId: 'name-1234', 
  keyFilename: './keyfile.json'
});

generateThumbnail函数

exports.generateThumbnail = functions.database.ref('/data/${dataID}/childData/${childDataID/image/name').onCreate(image => {

  const dataID = image.params.dataID
  const childDataID = image.params.childDataID 
  const fileName = image.data.val()

  //get your project storage bucket id
  const storageBucket = functions.config().firebase.storageBucket
  //path to image
  const imagePath = `${dataID}/${childDataID}`
  //open bucket
  const bucket = gcs.bucket(storageBucket)
  //location of the image in the bucket
  const object = bucket.file(imagePath)

  const fileBucket = object.bucket; // The Storage bucket that contains the file.
  const filePath = object.name; // File path in the bucket.

  const metadata = {
    contentType: 'image/jpeg'
  };

  // We add a 'thumb_' prefix to thumbnails file name. That's where we'll upload the thumbnail.
  const thumbFileName = `thumb_${fileName}`;
  const thumbFilePath = path.join(path.dirname(filePath), thumbFileName);
  // Create write stream for uploading thumbnail
  const thumbnailUploadStream = bucket.file(thumbFilePath).createWriteStream({metadata});

  // Create Sharp pipeline for resizing the image and use pipe to read from bucket read stream
  const pipeline = sharp();
  pipeline
    .resize(400, 400)
    .max()
    .pipe(thumbnailUploadStream);


  bucket.file(filePath).createReadStream().pipe(pipeline);

  const streamAsPromise = new Promise((resolve, reject) =>
    thumbnailUploadStream.on('finish', resolve).on('error', reject));

  return streamAsPromise.then(() => {
    console.log('Thumbnail created successfully');

    var today = new Date();
    var dd = today.getDate();
    var mm = today.getMonth() + 1; //January is 0!
    const yyyy = today.getFullYear() + 5; // add a few years

    if (dd < 10) {
      dd = '0' + dd
    } 

    if (mm < 10) {
      mm = '0' + mm
    } 

    today = mm + '-' + dd + '-' + yyyy;

    bucket.file(filePath).getSignedUrl({
      action: 'read',
      expires: today
    }, function(err, url) {
      if (err) {
        console.error(err);
        return;
      }
      //add thumb image url to message (in database)
      return admin.database().ref(`/${dataID}/childData/${childDataID}`).child('image').update({ 
        thumb: url
      })
    });
  });
})