文档

编写处理GetObject请求的函数

更新时间:

通过对象FC接入点访问GetObject API时,将触发您所绑定的函数计算服务中的函数,并在函数中配合WriteGetObjectResponse接口实现自定义返回数据和响应标头。

前提条件

  • 已创建对象FC接入点。具体操作,请参见创建对象FC接入点

  • OSS Java SDK为3.17.2及以上版本。

  • OSS Python SDK为2.18.3及以上版本。

操作步骤

  1. 编写处理GetObject请求的函数示例。

    示例一:通过转换后的图片进行响应

    Java

    import com.aliyun.fc.runtime.Context;
    import com.aliyun.fc.runtime.Credentials;
    import com.aliyun.fc.runtime.StreamRequestHandler;
    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.ObjectMetadata;
    import com.aliyun.oss.model.VoidResult;
    import com.aliyun.oss.model.WriteGetObjectResponseRequest;
    import org.codehaus.jettison.json.JSONException;
    import org.codehaus.jettison.json.JSONObject;
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.*;
    import java.util.Scanner;
    
    public class Example1 implements StreamRequestHandler {
        // Endpoint以华北1(青岛)为例。
        String endpoint = "https://oss-cn-qingdao.aliyuncs.com";
        private static int status = 200;
    
        public static String convertToString(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
            return scanner.hasNext() ? scanner.next() : "";
        }
    
        @Override
        public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            Credentials creds = context.getExecutionCredentials();
            // 从上下文中获取访问密钥。
            OSS ossClient = new OSSClientBuilder().build(endpoint, creds.getAccessKeyId(), creds.getAccessKeySecret(), creds.getSecurityToken());
    
    
            try {
                String result = convertToString(inputStream);
                JSONObject jsonObject = new JSONObject(result);
                String route = jsonObject.getJSONObject("getObjectContext").getString("outputRoute");
                String token = jsonObject.getJSONObject("getObjectContext").getString("outputToken");
                // 通过调用BufferedImage创建200*200像素的对象,并为该对象绘制红色的矩形框。
                // 完成以上调整后,将内容写入WriteGetObjectResponse请求的主体中。
                BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphics = image.createGraphics();
                graphics.setColor(Color.RED);
                graphics.fillRect(0, 0, 200, 200);
                graphics.dispose();
    
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ImageIO.write(image, "png", baos);
                WriteGetObjectResponseRequest writeGetObjectResponseRequest = new WriteGetObjectResponseRequest(route, token, status,new ByteArrayInputStream(baos.toByteArray()));
    
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentLength(baos.size());
                writeGetObjectResponseRequest.setMetadata(metadata);
    
                VoidResult voidResult = ossClient.writeGetObjectResponse(writeGetObjectResponseRequest);
                System.out.println("getRequestId:"+voidResult.getRequestId());
                System.out.println("status:"+voidResult.getResponse().getStatusCode());
                System.out.println("Headers:"+voidResult.getResponse().getHeaders().toString());
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message: " + oe.getMessage());
                System.out.println("Error Code:       " + oe.getErrorCode());
                System.out.println("Request ID:      " + oe.getRequestId());
                System.out.println("Host ID:           " + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message: " + ce.getMessage());
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                ossClient.shutdown();
            }
        }
    }
    

    Python

    # -*- coding: utf-8 -*-
    import io
    from PIL import Image
    import oss2
    import json
    
    # Endpoint以华北1(青岛)为例。
    endpoint = 'http://oss-cn-qingdao.aliyuncs.com'
    fwd_status = '200'
    
    # Fc function entry
    def handler(event, context):
    
        evt = json.loads(event)
        creds = context.credentials
        # do not forget security_token
        auth = oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds.security_token)
    
        headers = dict()    
    
        event_ctx = evt["getObjectContext"]
        route = event_ctx["outputRoute"]
        token = event_ctx["outputToken"]
        print(evt)
    
        endpoint = route
        service = oss2.Service(auth, endpoint)
        # 通过调用Image方法创建200*200像素的对象,并为该对象绘制红色的矩形框。
        # 完成以上调整后,将内容写入write_get_object_response请求的主体中。
        image = Image.new('RGB', (200, 200), color=(255, 0, 0))
        transformed = io.BytesIO()
        image.save(transformed, "png")
    
        resp = service.write_get_object_response(route, token, fwd_status, transformed.getvalue(), headers)
    
        print('status: {0}'.format(resp.status))
        print(resp.headers)
    
        return 'success'

    示例二:通过压缩内容进行响应

    Java

    import com.aliyun.fc.runtime.Context;
    import com.aliyun.fc.runtime.Credentials;
    import com.aliyun.fc.runtime.StreamRequestHandler;
    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.OSSObject;
    import com.aliyun.oss.model.ObjectMetadata;
    import com.aliyun.oss.model.VoidResult;
    import com.aliyun.oss.model.WriteGetObjectResponseRequest;
    import org.codehaus.jettison.json.JSONException;
    import org.codehaus.jettison.json.JSONObject;
    import java.io.*;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Scanner;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipOutputStream;
    
    public class Example2 implements StreamRequestHandler {
        // Endpoint以华北1(青岛)为例。
        String endpoint = "https://oss-cn-qingdao.aliyuncs.com";
        // 填写object名称。
        String fileName = "examplefile.txt";
        // 本地临时生成的压缩包路径。
        String path = "test.zip";
        private static int status = 200;
    
        public static String convertToString(InputStream inputStream) {
            Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
            return scanner.hasNext() ? scanner.next() : "";
        }
    
        public static void convertToZip(InputStream inputStream, String fileName, String path) throws IOException {
            FileOutputStream fos = new FileOutputStream(path);
            ZipOutputStream zipOut = new ZipOutputStream(fos);
            ZipEntry zipEntry = new ZipEntry(fileName);
            zipOut.putNextEntry(zipEntry);
    
            byte[] bytes = new byte[1024];
            int length;
            while((length = inputStream.read(bytes)) >= 0) {
                zipOut.write(bytes, 0, length);
            }
    
            zipOut.close();
            inputStream.close();
            fos.close();
        }
    
        @Override
        public void handleRequest(InputStream inputStream, OutputStream outputStream, Context context) throws IOException {
            Credentials creds = context.getExecutionCredentials();
            // 从上下文中获取访问密钥。
            System.out.println("getAccessKeyId: "+creds.getAccessKeyId());
            System.out.println("getAccessKeySecret: "+creds.getAccessKeySecret());
            OSS ossClient = new OSSClientBuilder().build(endpoint, creds.getAccessKeyId(), creds.getAccessKeySecret(), creds.getSecurityToken());
    
            try {
                String result = convertToString(inputStream);
                JSONObject jsonObject = new JSONObject(result);
                String route = jsonObject.getJSONObject("getObjectContext").getString("outputRoute");
                String token = jsonObject.getJSONObject("getObjectContext").getString("outputToken");
                String inputOssUrl = jsonObject.getJSONObject("getObjectContext").getString("inputOssUrl");
    
                System.out.println("jsonObject:"+jsonObject);
                System.out.println("inputOssUrl: "+inputOssUrl);
    
                Map<String, String> customHeaders = new HashMap<String, String>();
                URL signedUrl = new URL(inputOssUrl);
                OSSObject ossObject = ossClient.getObject(signedUrl, customHeaders);
                System.out.println("getObject StatusCode: "+ossObject.getResponse().getStatusCode());
    
                // 把通过签名url获取到的文件进行压缩后上传。
                convertToZip(ossObject.getObjectContent(), fileName, path);
                File file = new File(path);
                FileInputStream fis = new FileInputStream(file);
    
                WriteGetObjectResponseRequest writeGetObjectResponseRequest = new WriteGetObjectResponseRequest(route, token, status, fis);
    
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentLength(file.length());
                writeGetObjectResponseRequest.setMetadata(metadata);
    
                VoidResult voidResult = ossClient.writeGetObjectResponse(writeGetObjectResponseRequest);
                System.out.println("getRequestId:"+voidResult.getRequestId());
                System.out.println("status:"+voidResult.getResponse().getStatusCode());
                System.out.println("Headers:"+voidResult.getResponse().getHeaders().toString());
                // 删除临时生成的压缩包。
                file.delete();
            } catch (OSSException oe) {
                System.out.println("Caught an OSSException, which means your request made it to OSS, "
                        + "but was rejected with an error response for some reason.");
                System.out.println("Error Message: " + oe.getMessage());
                System.out.println("Error Code:       " + oe.getErrorCode());
                System.out.println("Request ID:      " + oe.getRequestId());
                System.out.println("Host ID:           " + oe.getHostId());
            } catch (ClientException ce) {
                System.out.println("Caught an ClientException, which means the client encountered "
                        + "a serious internal problem while trying to communicate with OSS, "
                        + "such as not being able to access the network.");
                System.out.println("Error Message: " + ce.getMessage());
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {            
                ossClient.shutdown();
            }
        }
    }
    

    Python

    # -*- coding: utf-8 -*-
    import os
    import oss2
    import json
    import gzip
    import requests
    # Endpoint以华北1(青岛)为例。
    endpoint = 'http://oss-cn-qingdao.aliyuncs.com'
    fwd_status = '200'
    
    # 填写object名称。
    fileName = "examplefile.txt"
    # 本地临时生成的压缩包路径。
    path = 'test.zip'
    
    def handler(event, context):
    
        evt = json.loads(event)
        creds = context.credentials
        # 从上下文中获取访问密钥。
        auth = oss2.StsAuth(creds.access_key_id, creds.access_key_secret, creds.security_token)
    
        headers = dict()  
    
        event_ctx = evt["getObjectContext"]
        route = event_ctx["outputRoute"]
        token = event_ctx["outputToken"]
        inputOssUrl = event_ctx["inputOssUrl"]
        print(evt)
    
        endpoint = route   
        resp = requests.get(inputOssUrl)
    
        # 把通过签名URL获取到的文件进行压缩后上传。
        g = gzip.GzipFile(filename=fileName, mode="wb", compresslevel=9, fileobj=open(path, 'wb'))
        g.write(resp.content)
        g.close()
    
        service = oss2.Service(auth, endpoint)
        with open(path, 'rb') as fileobj:
            resp = service.write_get_object_response(route, token, fwd_status, fileobj, headers)
            print('status: {0}'.format(resp.status))
            print(resp.headers)
    
        # 删除临时生成的压缩包。
        os.remove(path)
        return 'success'
  2. 部署函数。

    Java

    1. 自行打包.jar文件。

    2. 将.jar文件上传至函数计算控制台。

      1. 登录函数计算控制台,单击右上角返回函数计算2.0

      2. 在左侧导航栏,单击服务及函数

      3. 在顶部导航栏,选择华北1(青岛)地域。

      4. 服务列表页面,单击已创建的服务,然后单击已创建的运行环境为Java 11的函数。

      5. 在函数详情页面,选择上传代码 > 上传JAR包

      6. 在弹出的对话框,选择已打包的.jar文件,勾选我想在选中文件后直接部署函数,然后单击保存并部署

    3. 根据函数示例对应修改请求处理程序(函数入口)。

      1. 在函数详情页面,单击函数配置页签。

      2. 环境信息区域,单击编辑

      3. 修改请求处理程序(函数入口)

        当运行环境为Java时,当前值的格式为[package].[class]::[method]。如果当前值为 example.HelloFC::handleRequest,则在函数被触发时,将执行example包中HelloFC类下的handleRequest函数。您需要根据处理GetObject请求的函数示例的实际情况修改当前值,例如com.aliyun.sts.sample.Example1::handleRequest

    Python

    1. 服务列表页面,单击已创建的服务,然后单击已创建的运行环境为Python 3.10的函数。

    2. 在函数详情页面,单击函数代码页签,然后选择Terminal > New Terminal

    3. 在TERMINAL面板,输入以下命令更新OSS Python SDK版本。

      pip install oss2 -t .
    4. 将index.py中的代码示例替换为Python处理GetObject请求的函数示例,然后单击部署函数

后续步骤

使用对象FC接入点

  • 本页导读 (1)
文档反馈