This topic describes how to configure an Object Storage Service (OSS) trigger in the Function Compute console, including how to create an OSS trigger for a function, configure function input parameters, write function code, and test the function. In this topic, an OSS trigger is created to trigger function execution when a new object is added to an OSS bucket.

Scenarios

You can configure an OSS trigger and set the prefix to source in the trigger rule. When an image is stored in the source directory of the specified OSS bucket, the function is automatically triggered. The function scales the image and stores the processed image in the processed directory of the same bucket. The source/serverless.png image is processed as the processed/serverless.png image.

Before you begin

Step 1: Create an OSS trigger

  1. Log on to the Function Compute console. In the left-side navigation pane, click Services & Functions.
  2. In the top navigation bar, select a region. On the Services page, click the desired service.
  3. On the Functions page, click the function that you want to manage.
  4. On the function details page, click the Triggers tab, select the version or alias from the Version or Alias drop-down list, and then click Create Trigger.
  5. In the Create Trigger panel, specify related parameters. After you specify the parameters, click OK.
    ParameterDescriptionExample
    Trigger TypeThe type of the trigger. Select OSS. OSS
    NameThe name of the trigger. oss-trigger
    Version or AliasThe version or alias of the service. The default value is LATEST. If you want to create a trigger for another version or alias, select a version or alias from the Version or Alias drop-down list on the function details page. For more information about versions and aliases of a service, see Manage versions and Manage aliases. LATEST
    Bucket NameThe name of the OSS bucket. Select an OSS bucket from the drop-down list. bucket-zh****
    Object PrefixEnter the prefixes of the object names that you want to match. We recommend that you configure prefixes and suffixes to avoid additional costs that are generated by nested loops. If you specify the same event type for different triggers of a bucket, the prefixes or suffixes cannot be repeated. For more information, see Rules for triggering native OSS triggers.
    Important The prefix cannot start with a forward slash (/). Otherwise, the OSS trigger fails to be triggered.
    source
    Object SuffixEnter the suffixes of the object name that you want to match. We recommend that you configure prefixes and suffixes to avoid additional costs that are generated by function execution loops. If you specify the same event type for different triggers of a bucket, the prefixes or suffixes cannot be repeated. For more information, see Rules for triggering native OSS triggers. zip
    Trigger EventThe trigger event. Select one or more trigger events from the drop-down list. For more information about Object Storage Service (OSS) events, see OSS events.

    In this example, oss:ObjectCreated:PutObject is selected.

    oss:ObjectCreated:PutObject
    Role NameThe name of the role. Select AliyunOSSEventNotificationRole.
    Note After you configure the preceding parameters, click OK. If this is the first time that you create a trigger of this type, click Authorize Now in the message that appears.
    AliyunOSSEventNotificationRole

    After the trigger is created, it is displayed on the Triggers tab. To modify or delete an existing trigger, see Trigger management.

Step 2: Configure the input parameters of the function

The OSS event source is passed to the function in the form of event, which acts as an input parameter. You can manually pass event to the function to trigger the function.

  1. On the function details page, click the Code tab and click the xialatubiao icon. From the drop-down list that appears, select Configure Test Parameters.
  2. In the Configure Test Parameters panel, click the Create New Test Event or Modify Existing Test Event tab, and specify Event Name and the event content. After you specify the parameters, click OK.

    The event parameter is an input parameter of Function Compute. When you create an object in or delete an object from a specified OSS bucket, the event data in JSON format is sent to the bound function. Sample code:

    {
        "events":[
            {
                "eventName":"ObjectCreated:PutObject",
                "eventSource":"acs:oss",
                "eventTime":"2022-08-13T06:45:43.000Z",
                "eventVersion":"1.0",
                "oss":{
                    "bucket":{
                        "arn":"acs:oss:cn-shanghai:123456789:bucketname",
                        "name":"testbucket",
                        "ownerIdentity":"164901546557****"
                    },
                    "object":{
                        "deltaSize":122539,
                        "eTag":"688A7BF4F233DC9C88A80BF985AB****",
                        "key":"image/a.jpg",
                        "size":122539
                    },
                    "ossSchemaVersion":"1.0",
                    "ruleId":"9adac8e253828f4f7c0466d941fa3db81161****"
                },
                "region":"cn-shanghai",
                "requestParameters":{
                    "sourceIPAddress":"140.205.XX.XX"
                },
                "responseElements":{
                    "requestId":"58F9FF2D3DF792092E12044C"
                },
                "userIdentity":{
                    "principalId":"164901546557****"
                }
            }
        ]
    }          
    The following table describes the fields in event.
    ParameterTypeExampleDescription
    eventNameStringObjectCreated:PutObjectThe type of the event.
    eventSourceStringacs:ossThe event source. Set the value to acs:oss.
    eventTimeString2022-08-13T06:45:43.000ZThe time when the event occurs. The time follows the ISO 8601 standard format.
    eventVersionString1.0The version of the event protocol.
    ossMapThe content of the OSS event.
    bucketMapDetails of the OSS bucket.
    nameStringtestbucketThe name of the bucket.
    arnStringacs:oss:cn-shanghai:123456789:bucketnameThe Alibaba Cloud Resource Name (ARN) of the bucket.
    ownerIdentityString164901546557****The ID of the user that created the bucket.
    objectMapDetails of the OSS object.
    sizeInt122539The size of the OSS object. Unit: byte.
    deltaSizeInt122539The variation of the size of the OSS object. Unit: byte.
    • If an object is added, the value of this parameter indicates the size of the object.
    • If a new object overwrites the object that has the identical name, the value of this parameter specifies the size difference between the new object and the original object.
    eTagString688A7BF4F233DC9C88A80BF985AB****The tag of the object.
    keyStringimage/a.jpgThe name of the object.
    ossSchemaVersionString1.0The version of the OSS schema.
    ruleIdString9adac8e253828f4f7c0466d941fa3db81161****The ID of the rule that matches the event.
    regionStringcn-shanghaiThe region in which the bucket resides.
    requestParametersMapThe request parameters.
    sourceIPAddressString140.205.XX.XXThe IP address from which the request is sent.
    responseElementsMapThe response elements.
    requestIdString58F9FF2D3DF792092E12044CThe ID of the request.
    userIdentityMapThe property of the user.
    principalIdString164901546557****The ID of the Alibaba Cloud account that initiated the request.

Step 3: Write the function code and test the function

After you create the trigger, you can write function code and test the function to verify whether the code is correct. When an OSS event occurs, the function execution is triggered.

Warning Avoid loop in the code. For example, when objects are uploaded to an OSS bucket, the upload operation triggers a function. Then, this function generates one or more objects to be written to the OSS bucket, and the write operation triggers this function again. This lead to a loop. For more information about the message routing feature, see Rules for triggering native OSS triggers.
  1. On the function details page, click the Code tab, edit the function code in the code editor, and then click Deploy.

    Preparations and sample code:

    Note If you want to read and write OSS resources in your function, we recommend that you use the internal endpoint of OSS to access OSS resources to prevent costs that are generated by access over the Internet. For more information about the format of OSS internal endpoints, see Regions and endpoints.
    /*Preparations:
    1. Run the following command on the client to create the package.json file and install the jimp module. 
      a. Run npm init on the client to create the package.json file.
      b. Run npm install jimp on the client to install jimp.
    2. Make sure that handler of the function is index.handler. 
    */
    
    'use strict';
     console.log('Loading function ...');
     var oss = require('ali-oss').Wrapper;
     var fs = require('fs');
     var jimp = require("jimp");
     module.exports.handler = function (eventBuf, ctx, callback) {
         console.log('Received event:', eventBuf.toString());
         var event = JSON.parse(eventBuf);
         var ossEvent = event.events[0];
         // The OSS region is prefixed with oss-, such as oss-cn-shanghai-.
         var ossRegion = "oss-" + ossEvent.region;
         // Create an OSS client.
         var client = new oss({
             region: ossRegion,
             // Obtain the credential from the context.
             accessKeyId: ctx.credentials.accessKeyId,
             accessKeySecret: ctx.credentials.accessKeySecret,
             stsToken: ctx.credentials.securityToken
         });
         // Obtain the bucket name from the event.
         client.useBucket(ossEvent.oss.bucket.name);
         // Store the processed image to the processed/directory.
         var newKey = ossEvent.oss.object.key.replace("source/", "processed/");
         var tmpFile = "/tmp/processed.png";
         // Obtain the OSS object.
         console.log('Getting object: ', ossEvent.oss.object.key)
         client.get(ossEvent.oss.object.key).then(function (val) {
             // Read the content of the OSS object from the cache.
             jimp.read(val.content, function (err, image) {
                 if (err) {
                     console.error("Failed to read image");
                     callback(err);
                     return;
                 }
                 // Resize the image and save the processed image to tmp.
                 image.resize(128, 128).write(tmpFile, function (err) {
                     if (err) {
                         console.error("Failed to write image locally");
                         callback(err);
                         return;
                     }
                     // Upload the read object to the OSS bucket and rename the object.
                     console.log('Putting object: ', newKey);
                     client.put(newKey, tmpFile).then(function (val) {
                         console.log('Put object:', val);
                         callback(null, val);
                         return;
                     }).catch(function (err) {
                         console.error('Failed to put object: %j', err);
                         callback(err);
                         return
                     });
                 });
             });
         }).catch(function (err) {
             console.error('Failed to get object: %j', err);
             callback(err);
             return
         });
     };
    # Preparations:
    #1. Make sure that the Resource Access Management (RAM) role configured for the service to which the function belongs has the permissions to access OSS. You can log on to the RAM console and grant the role permissions to access OSS. 
    #2. Make sure that handler of the function is index.handler. 
    
    # -*- coding: utf-8 -*-
    import oss2, json
    from wand.image import Image
    def handler(event, context):
        evt = json.loads(event)
        creds = context.credentials
        # Required by OSS sdk
        auth=oss2.StsAuth(
            creds.access_key_id,
            creds.access_key_secret,
            creds.security_token)
        evt = evt['events'][0]
        bucket_name = evt['oss']['bucket']['name']
        endpoint = 'oss-' +  evt['region'] + '-internal.aliyuncs.com'
        bucket = oss2.Bucket(auth, endpoint, bucket_name)
        objectName = evt['oss']['object']['key']
        # Processed images will be saved to processed/
        newKey = objectName.replace("source/", "processed/")
        remote_stream = bucket.get_object(objectName)
        if not remote_stream:
            return
        remote_stream = remote_stream.read()
        with Image(blob=remote_stream)  as img:
            with img.clone() as i:
                i.resize(128, 128)
                new_blob = i.make_blob()
                bucket.put_object(newKey, new_blob) 
    /*Preparations:
    1. Make sure that the RAM role configured for the service to which the function belongs has the permissions to access OSS. You can log on to the RAM console and grant the role permissions to access OSS. 
    2. Make sure that handler of the function is index.handler. 
    */
    
    <?php
      use OSS\OssClient;
      function handler($event, $context) {
          $event           = json_decode($event, $assoc = true);
          $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'];
          $newKey = str_replace("source/", "processed/", $objectName);
          try {
              $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false, $securityToken);
              $content = $ossClient->getObject($bucketName , $objectName);
              if ($content == null || $content == "") {
                 return;
              }
             $imagick = new Imagick();
             $imagick->readImageBlob($content);
             $imagick->resizeImage(128, 128, Imagick::FILTER_LANCZOS, 1);
             $ossClient->putObject($bucketName, $newKey, $imagick->getImageBlob());
         } catch (OssException $e) {
             print($e->getMessage());
         }
     } 
    /*Preparations:
    1. Add the following dependencies to the pom.xml file. 
    <dependencies>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-core</artifactId>
          <version>1.4.1</version>
        </dependency>
        <dependency>
          <groupId>com.aliyun.fc.runtime</groupId>
          <artifactId>fc-java-event</artifactId>
          <version>1.2.0</version>
        </dependency>
    </dependencies>
    2. Make sure that handler of the function is example.App::handleRequest. 
    */
    
    package example;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import com.aliyun.fc.runtime.Context;
    import com.aliyun.fc.runtime.StreamRequestHandler;
    import com.aliyun.fc.runtime.event.OSSEvent;
    
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.DeserializationFeature;
    import com.fasterxml.jackson.databind.ObjectMapper;
    
    public class App implements StreamRequestHandler {
    
        private static final ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    
        @Override
        public void handleRequest(
                InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            OSSEvent ossEvent = mapper.readValue(inputStream, new TypeReference<OSSEvent>() {});
            for (OSSEvent.Event event : ossEvent.events) {
                outputStream.write(String.format("received %s from %s @ %s", event.eventName, event.eventSource, event.region).getBytes());
                outputStream.write(String.format("received bucket %s", event.oss.bucket.arn).getBytes());
                outputStream.write(String.format("received object %s and it's size is %s", event.oss.object.key, event.oss.object.size).getBytes());
            }
        }
    } 
  2. Click the Code tab and click Test Function.
    After the function is executed, you can view the result on the Code tab.

FAQ

Q: How do I set Trigger Event if I want to trigger the function execution only once when an object is uploaded to OSS?

A: You can set Trigger Event to oss:ObjectCreated:PutObject, oss:ObjectCreated:PostObject, and oss:ObjectCreated:CompleteMultipartUpload.

When an object is uploaded by using multipart upload, the oss:ObjectCreated:InitiateMultipartUpload, oss:ObjectCreated:UploadPart, and oss:ObjectCreated:CompleteMultipartUpload events are triggered in sequence. For example, if you set Trigger Event of the function trigger to oss:ObjectCreated:*, the function is invoked five times when a 12 MB file is uploaded by using the OSS browser tool and the part size is set to 5 MB. The events for the five invocations are: oss:ObjectCreated:InitiateMultipartUpload, oss:ObjectCreated:UploadPart, oss:ObjectCreated:UploadPart, oss:ObjectCreated:UploadPart and oss:ObjectCreated:CompleteMultipartUpload.

For more information about the trigger rules of OSS triggers, see What do I do if a trigger cannot trigger function execution?.

Related operations

In addition to the Function Compute console, you can configure triggers by using the following methods:
  • Use Serverless Devs to configure triggers. For more information, see Serverless Devs.
  • Use SDKs to configure triggers. For more information, see SDKs.

To modify or delete an existing trigger, see Trigger management.