使用 Google Cloud Functions Node JS 10 仅从特定存储桶目录复制事件驱动的文件

Posted

技术标签:

【中文标题】使用 Google Cloud Functions Node JS 10 仅从特定存储桶目录复制事件驱动的文件【英文标题】:Event driven file copy from only specific bucket directory with Google Cloud Functions Node JS 10 【发布时间】:2020-03-08 00:23:43 【问题描述】:

我得到了一个事件驱动的 Google Cloud Function (Node JS 10) 的帮助,可以将文件复制到另一个 Google Cloud Storage 存储桶中,并希望能更进一步。

我需要过滤这些触发器文件以仅从一个文件夹及其子目录复制文件,而不是整个存储桶中的任何文件。

所以为免生疑问,如果我有:

bucket-a/folder-1/folder-a/folder-x

bucket-a/folder-2/folder-b/folder-y

bucket-a/folder-3/folder-c/folder-z

我想复制所有登陆 bucket-a/folder-2/folder-b 及其所有子目录的文件。

但不要复制位于文件夹 1、文件夹 3 或其任何子目录中的任何文件。

只是不确定在何处或如何将“if”参数引入已经运行良好的内容。

这是目前为止的代码:

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

exports.helloGCS = (event, context) => 
  const storage = new Storage();
  const gcsEvent = event;
  const sourceFileBucket = gcsEvent.bucket
  const sourcePathOnly = gcsEvent.name
  const sourceFolder = sourcePathOnly.split('/').slice(-2) 
  const destFileBucket = 'my_dest_bucket'

  storage
  .bucket(sourceFileBucket)
  .file(sourcePathOnly)
  .copy(storage.bucket(destFileBucket).file(sourceFolder[0] + '/' + sourceFolder[1])); 

;

任何帮助将不胜感激。


这是给我 sourcePathOnly 未定义错误的当前代码,并且还在根目录下创建了两个文件夹,folder-2 和 folder-b:

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

exports.helloGCS = (event, context) => 
    const gcsEvent = event;
    const storage = new Storage()


  // Process only if it's in the correct folder
  if (sourcePathOnly.indexOf('folder-2/folder-b') > -1) 

    const sourcePathOnly = gcsEvent.name
    const sourceFileBucket = gcsEvent.bucket
    const sourceFolder = sourcePathOnly.split('/').slice(-2) 
    const destFileBucket = 'my_dest_bucket'

    storage
    .bucket(sourceFileBucket)
    .file(sourcePathOnly)
    .copy(storage.bucket(destFileBucket).file(sourceFolder[0] + '/' + 
    sourceFolder[1])); 
  

【问题讨论】:

【参考方案1】:

Cloud Storage 和 Cloud Storage 上的事件功能非常强大。但是,您无法设置触发事件的条件。

顺便说一句,你必须在你的代码中设置一个“手动过滤器”

exports.helloGCS = (event, context) => 
  const gcsEvent = event;
  const sourcePathOnly = gcsEvent.name

  // Process only if it's in the correct folder
  if (sourcePathOnly.indexOf('folder-2/folder-b') > -1) 
    const storage = new Storage();
    const sourceFileBucket = gcsEvent.bucket
    const sourceFolder = sourcePathOnly.split('/').slice(-2) 
    const destFileBucket = 'my_dest_bucket'

    storage
    .bucket(sourceFileBucket)
    .file(sourcePathOnly)
    .copy(storage.bucket(destFileBucket).file(sourceFolder[0] + '/' + 
    sourceFolder[1])); 
  

现在您只处理来自您想要的 src 路径的文件。

不好的是,您的函数将在存储桶中创建的每个文件上触发,因此您的函数将启动、执行检查并退出。您将因为什么都不做而收取 100 毫秒的处理费用。 我已经提出了关于这个主题的功能请求。

【讨论】:

非常感谢纪尧姆。不幸的是,收到“错误:函数执行失败。详细信息:无法读取未定义的属性“拆分””消息。 希望他们实现您的功能要求。与此同时,希望它不应该是大量文件。 ...我查看了调用云函数的成本...似乎是每百万次调用大约 0.40 美元。每美元大约有 250 万个新文件。 是的,限制很高,每个项目每月有 2M 免费。但我不知道您旁边的其他调用,但这会增加每月项目的调用次数和 CPU/内存消耗,并且您会很快达到计费限制(高于免费套餐) 关于代码,我不明白为什么拆分会有问题。我没有更改这部分,我只是添加了一个 if 并使用复制粘贴移动了一些行。您是否仔细检查了您的代码?【参考方案2】:

存储桶的工作方式与文件系统不完全相同,您可以在link 上查看 Google Cloud Storage 结构和层次结构信息。

为了能够过滤您指定的需要,我建议您列出存储桶中的所有对象,然后从您想要的文件夹中过滤您需要的对象。

当您将某些内容存储在存储桶中时,格式将是这样的:

gsutil 将使用 delimiter="/" 和 prefix="abc" 为指定存储桶发出存储桶列表请求。然后会检查bucket列表结果,判断bucket中是否有路径以gs://your-bucket/abc/开头的对象,判断是把target当作对象名还是目录名。反过来,这会影响您创建的对象的名称:如果上述检查表明存在“abc”目录,您最终将得到对象 gs://your-bucket/abc/your-file;否则你会得到对象 gs://your-bucket/abc。

希望这对您有所帮助。告诉我。

【讨论】:

感谢 Stefan 的链接。

以上是关于使用 Google Cloud Functions Node JS 10 仅从特定存储桶目录复制事件驱动的文件的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Google Cloud SDK 列出所有 Cloud Functions?

使用 Cloud Functions for Firebase 和 @google-cloud/storage 删除图像时出现问题

Google Cloud Functions 部署问题

使用 Google Cloud Functions 的微服务 API 网关

Google Cloud Platform:Cloud Functions 与 App Engine

具有 Google Cloud Functions 的 Google Cloud Endpoints [关闭]