配置原生OSS触发器

更新时间: 2023-12-22 15:48:36

您可以在函数计算控制台创建并配置原生OSS触发器,当在OSS上发生特定事件时会自动触发函数执行。这可以让您轻松响应如文件上传等事件,无需在代码中增加监听事件逻辑即可快速实现完整的流程。

示例场景

您可以配置一个OSS触发器,并将其文件前缀设置为source。当有图片存入指定的OSS Bucket中的source目录下,会自动触发函数执行。函数将图片进行缩放处理后存放到同一个Bucket的processed目录下,即将source/a.png处理为processed/a.png

使用限制

  • 原生OSS触发器,一个Bucket最多支持关联10个触发器。

    说明

    如果您需要在一个Bucket内,关联更多的OSS触发器,可以选择创建EventBridge类别的OSS触发器。通常情况下,不推荐一个Bucket关联10个以上的触发器。如需创建,建议您创建新的Bucket,并基于新的Bucket创建触发器。

  • 原生OSS触发器和EventBridge类别的OSS触发器配置的文件前缀和文件后缀都不支持模糊匹配和正则匹配。如果想配置多个文件前缀和文件后缀,可使用EventBridge类别的OSS触发器。

前提条件

步骤一:创建OSS触发器

  1. 登录函数计算控制台,在左侧导航栏,单击服务及函数
  2. 在顶部菜单栏,选择地域,然后在服务列表页面,单击目标服务。
  3. 函数管理页面,单击目标函数名称。

  4. 在函数详情页面,单击触发器管理页签,从版本或别名下拉列表选择要创建触发器的版本或别名,然后单击创建触发器

  5. 在创建触发器面板,填写相关信息。然后单击确定

    配置项

    操作

    本文示例

    触发器类型

    选择对象存储 OSS

    对象存储 OSS

    名称

    填写自定义的触发器名称。

    oss-trigger

    版本或别名

    默认值为LATEST,如果您需要创建其他版本或别名的触发器,需先在函数详情页的版本或别名下拉列表选择该版本。关于版本和别名的简介,请参见管理版本管理别名

    LATEST

    Bucket 名称

    选择已创建的OSS Bucket。

    testbucket

    文件前缀

    输入要匹配的文件名称的前缀。建议您配置文件前缀和后缀,避免触发事件嵌套循环触发引起额外费用。此外,一个Bucket的不同触发器如果指定了相同的事件类型,则前缀和后缀不能重复。详细信息,请参见OSS触发器触发规则

    重要

    文件前缀不能以/开头,否则会导致OSS触发器无法被触发。

    source

    文件后缀

    输入要匹配的文件名称的后缀。强烈建议您配置前缀和后缀,避免触发事件嵌套循环触发引起额外费用。另外,一个Bucket的不同触发器如果指定了相同的事件类型,则前缀和后缀不能重复。详细信息,请参见OSS触发器触发规则

    png

    触发事件

    选择一个或多个触发事件。关于对象存储OSS的事件类型,请参见OSS事件定义

    oss:ObjectCreated:PutObjectoss:ObjectCreated:PostObjectoss:ObjectCreated:CompleteMultipartUpload

    角色名称

    选择AliyunOSSEventNotificationRole

    说明

    如果您第一次创建该类型的触发器,则需要在单击确定后,在弹出的对话框中选择立即授权

    AliyunOSSEventNotificationRole

    创建完成后,在触发器名称列表中显示已创建的触发器。如需对创建的触发器进行修改或删除,具体操作,请参见触发器管理

步骤二:配置函数入口参数

OSS事件源会以event的形式作为输入参数传递给函数,您可以手动将event传给函数模拟触发事件。

  1. 在函数详情页面,单击函数代码页签,然后单击测试函数右侧xialatubiao图标,从下拉列表中,选择配置测试参数

  2. 配置测试参数面板,选择创建新测试事件编辑已有测试事件页签,填写事件名称和事件内容。然后单击确定

    说明

    event内容请根据创建触发器时的信息进行配置,同时需要确保配置的Bucket中存在指定的文件(本文示例中是source/a.png文件),否则会无法触发函数执行,或者函数执行会失败。

    event是函数计算的入口参数,当指定的OSS Bucket发生对象创建时,会将事件数据以JSON格式发送给绑定的函数。具体格式如下所示。

    {
        "events": [
            {
                "eventName": "ObjectCreated:PutObject",
                "eventSource": "acs:oss",
                "eventTime": "2022-08-13T06:45:43.000Z",
                "eventVersion": "1.0",
                "oss": {
                    "bucket": {
                        "arn": "acs:oss:cn-hangzhou:123456789:testbucket",
                        "name": "testbucket",
                        "ownerIdentity": "164901546557****"
                    },
                    "object": {
                        "deltaSize": 122539,
                        "eTag": "688A7BF4F233DC9C88A80BF985AB****",
                        "key": "source/a.png",
                        "size": 122539
                    },
                    "ossSchemaVersion": "1.0",
                    "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****"
                },
                "region": "cn-hangzhou",
                "requestParameters": {
                    "sourceIPAddress": "140.205.XX.XX"
                },
                "responseElements": {
                    "requestId": "58F9FF2D3DF792092E12044C"
                },
                "userIdentity": {
                    "principalId": "164901546557****"
                }
            }
        ]
    }

    event参数中不同属性字段的解释如下表所示。

    参数

    类型

    示例值

    描述

    eventName

    String

    ObjectCreated:PutObject

    事件类型。

    eventSource

    String

    acs:oss

    事件源,固定为acs:oss

    eventTime

    String

    2022-08-13T06:45:43.000Z

    事件产生的时间。使用ISO-8601标准时间格式。

    eventVersion

    String

    1.0

    事件协议的版本。

    oss

    Map

    OSS事件内容。

    bucket

    Map

    bucket参数内容。

    name

    String

    testbucket

    Bucket的名称。

    arn

    String

    acs:oss:cn-hangzhou:123456789:testbucket

    Bucket的唯一标识符。

    ownerIdentity

    String

    164901546557****

    创建Bucket的用户ID。

    object

    Map

    object参数内容。

    size

    Int

    122539

    object的大小。单位:Byte。

    deltaSize

    Int

    122539

    object的大小变化量。单位:Byte。

    • 如果新增一个文件,此参数的值表示文件大小。

    • 如果同名覆盖一个文件,此参数的值表示新文件与旧文件的大小差值。

    eTag

    String

    688A7BF4F233DC9C88A80BF985AB****

    Object的标签。

    key

    String

    source/a.png

    Object的名称。

    ossSchemaVersion

    String

    1.0

    OSS模式的版本号。

    ruleId

    String

    9adac8e253828f4f7c0466d941fa3db81161****

    事件匹配的规则ID。

    region

    String

    cn-hangzhou

    Bucket所在的地域。

    requestParameters

    Map

    请求参数。

    sourceIPAddress

    String

    140.205.XX.XX

    请求的源IP地址。

    responseElements

    Map

    响应元素。

    requestId

    String

    58F9FF2D3DF792092E12044C

    请求对应的Request ID。

    userIdentity

    Map

    用户属性。

    principalId

    String

    164901546557****

    请求发起者的阿里云账号ID。

步骤三:编写函数代码并测试

OSS触发器创建完成后,您可以开始编写函数代码并测试,以验证代码的正确性。在实际操作过程中,发生OSS事件时,函数会自动被触发执行。

警告

代码中一定要避免循环触发。一个典型的循环触发场景是OSS的某个Bucket上传文件事件触发函数执行,此函数执行完成后又生成了一个或多个文件再写回到OSS的Bucket里,这个写入动作又触发了函数执行,形成了链状循环。更多信息,请参见OSS触发器触发规则

  1. 在函数详情页面,单击函数代码页签,在代码编辑器中编写代码,然后单击部署代码

    • 支持在线编辑代码的运行环境的示例代码如下。

      说明

      如果您要在您的函数中读写OSS资源,建议使用OSS内网服务地址进行访问,避免使用公网访问,产生公网费用。关于OSS内网服务地址的格式,请参见访问域名和数据中心

      "use strict";
      /*
      本代码样例主要实现以下功能:
      *   1. 从event中解析出OSS事件触发相关信息。
      *   2. 根据以上获取的信息,初始化OSS客户端。
      *   3. 将源图片resize后持久化到OSS bucket下指定的目标图片路径,从而实现图片备份。
      
      
      This code sample mainly implements the following functions:
      * 1. Parse the OSS event trigger related information from the event.
      * 2. According to the above information, initialize the OSS client.
      * 3. Resize the source image and then store the processed image into the same bucket's copy folder to backup the image.
      */
      
      const OSS = require("ali-oss");
      
      exports.handler = async function(event, context, callback) {
          console.log("The content in context entity is: \n");
          console.dir(context);
      
          const {accessKeyId, accessKeySecret, securityToken} = context.credentials;
      
          const events = JSON.parse(event.toString()).events;
          console.log("The content in event entity is: \n");
          console.dir(events);
      
          let objectName = events[0].oss.object.key;
          let region = events[0].region;
          let bucketName = events[0].oss.bucket.name;
      
          // 连接目标OSS。
          // Connect to the target OSS
          const client = new OSS({
              region: region,
              accessKeyId: accessKeyId,
              accessKeySecret: accessKeySecret,
              stsToken: securityToken,
              bucket: bucketName,
              endpoint: "https://oss-" + region + "-internal.aliyuncs.com"
          });
      
          console.log("The client entity is: \n");
          console.dir(events);
      
          const targetImage = objectName.replace("source/", "processed/")
          // 将图片缩放为固定宽高128 px。
          const processStr = "image/resize,m_fixed,w_128,h_128"
          // 将源图片resize后再存储到目标图片路径。
          const result = await client.processObjectSave(
              objectName,
              targetImage,
              processStr,
              bucketName
          );
          console.log(result.res.status);
      
          callback(null, "done");
      }
      """
      本代码样例主要实现以下功能:
      * 从event中解析出OSS事件触发相关信息。
      * 根据以上获取的信息,初始化OSS bucket客户端。
      * 将源图片resize后持久化到OSS bucket下指定的目标图片路径,从而实现图片备份。
      
      
      This sample code is mainly doing the following things:
      * Get OSS processing related information from event.
      * Initiate OSS client with target bucket.
      * Resize the source image and then store the processed image into the same bucket's copy folder to backup the image.
      
      """
      
      # -*- coding: utf-8 -*-
      import oss2, json
      import base64
      
      def handler(event, context):
          # 可以通过context.credentials获取密钥信息。
          # Access keys can be fetched through context.credentials
          print("The content in context entity is: \n")
          print(context)
          creds = context.credentials
      
          # 设置权鉴,供OSS sdk使用。
          # Setup auth, required by OSS sdk.
          auth = oss2.StsAuth(
              creds.access_key_id,
              creds.access_key_secret,
              creds.security_token)
      
          print("The content in event entity is: \n")
          print(event)
          # Load event content.
          oss_raw_data = json.loads(event)
          # Get oss event related parameters passed by oss trigger.
          oss_info_map = oss_raw_data['events'][0]['oss']
          # Get oss bucket name.
          bucket_name = oss_info_map['bucket']['name']
          # Set oss service endpoint.
          endpoint = 'oss-' + oss_raw_data['events'][0]['region'] + '-internal.aliyuncs.com'
          # Initiate oss client.
          bucket = oss2.Bucket(auth, endpoint, bucket_name)
          object_name = oss_info_map['object']['key']
      
          # Download original image from oss bucket.
          remote_stream = bucket.get_object(object_name)
          if not remote_stream:
              print(f'{object_name} does not exist in bucket {bucket_name}')
              return
          # Processed images will be saved to processed/
          processed_path = object_name.replace('source/', 'processed/')
      
          # 将图片缩放为固定宽高128 px。
          style = 'image/resize,m_fixed,w_128,h_128'
          # 指定处理后图片名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如exampledir/example.jpg。
          process = "{0}|sys/saveas,o_{1},b_{2}".format(style,
              oss2.compat.to_string(base64.urlsafe_b64encode(oss2.compat.to_bytes(processed_path))),
              oss2.compat.to_string(base64.urlsafe_b64encode(oss2.compat.to_bytes(bucket_name))))
          result = bucket.process_object(object_name, process)
          print(result)
      /*本代码样例主要实现以下功能:
      *   1. 从request中解析出 endpoint,bucket,object。
      *   2. 根据以上获取的信息,初始化OSS客户端。
      *   3. 将源图片resize后持久化到OSS bucket下指定的目标图片路径,从而实现图片备份。
      *
      *This code sample mainly implements the following functions:
      * 1. Parse out endpoint, bucket, object from request.
      * 2. According to the information obtained above, initialize the OSS client.
      * 3. Resize the source image and then store the processed image into the same bucket's copy folder to backup the image.
      */
      <?php
      
      use RingCentral\Psr7\Response;
      use OSS\OssClient;
      use OSS\Core\OssException;
      
      function base64url_encode($data)
      {
          return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
      }
      
      function handler($event, $context) {
        $event           = json_decode($event, $assoc = true);
        /*
          阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
          建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
          本示例以从上下文中获取AccessKey/AccessSecretKey为例。
        */
        $accessKeyId     = $context["credentials"]["accessKeyId"];
        $accessKeySecret = $context["credentials"]["accessKeySecret"];
        $securityToken   = $context["credentials"]["securityToken"];
        $evt        = $event['events']{0};
        $bucketName = $evt['oss']['bucket']['name'];
        $endpoint   = 'oss-' . $evt['region'] . '-internal.aliyuncs.com';
        $objectName = $evt['oss']['object']['key'];
        $targetObject = str_replace("source/", "processed/", $objectName);
      
          try {
              // 连接OSS。
              // Connect to OSS.
              $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);
              // 将图片缩放为固定宽高128px。
              $style = "image/resize,m_fixed,w_128,h_128";
              $process = $style.
                 '|sys/saveas'.
                 ',o_'.base64url_encode($targetObject).
                 ',b_'.base64url_encode($bucketName);
              // 将图片 Resize 后保存到目标文件中。
              $result = $ossClient->processObject($bucketName, $objectName, $process);
              // 打印处理结果。
              print($result);
          } catch (OssException $e) {
              print_r(__FUNCTION__ . ": FAILED\n");
              printf($e->getMessage() . "\n");
          }
      
          print(__FUNCTION__ . ": OK" . "\n");
      
          return $targetObject;
      }
  2. 单击函数代码页签的测试函数

    执行完成后,您可以在函数代码页签的上方查看执行结果。

常见问题

相关文档

  • 如果您想了解可以配置的OSS事件类型,请参见OSS事件定义

  • 除了函数计算控制台,您还可以通过以下方式配置触发器:

    • 通过Serverless Devs工具配置触发器。更多操作,请参见触发器相关命令

    • 通过SDK配置触发器。更多操作,请参见SDK列表

  • 如果您需要对创建的触发器进行修改或删除,具体操作请参见更新触发器配置

  • 如果您需要在一个Bucket内关联10个以上的OSS触发器,请参见配置EventBridge类别的OSS触发器

  • 触发器相关问题

    • 如果您希望查看函数的执行触发了哪个事件,可以手动在代码逻辑中打印事件类型日志,具体请参见日志记录

    • 如果您希望在函数中调用另一个函数,可以使用API调用指定函数或使用函数工作流编排函数。如果调用的函数需要执行耗时操作且均为异步调用,可以配置异步调用目标服务。具体请参见函数可以相互调用吗?配置异步调用目标服务

阿里云首页 函数计算(旧版) 相关技术圈