通过对象FC接入点访问GetObject API时,将触发您所绑定的函数计算服务中的函数,并在函数中配合WriteGetObjectResponse接口实现自定义返回数据和响应标头。
前提条件
已创建对象FC接入点。具体操作,请参见创建对象FC接入点。
操作步骤
编写处理GetObject请求的函数示例。
Java
Java SDK要求3.17.2及以上版本。
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
Python SDK要求2.18.3及以上版本。
# -*- 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'
Go
Go SDK要求1.2.2及以上版本。
package main import ( "bytes" "context" "fmt" "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/fc-runtime-go-sdk/fc" "github.com/aliyun/fc-runtime-go-sdk/fccontext" "image" "image/color" "image/draw" "image/png" ) // 定义GetObjectContext结构体,该结构体包含输出路由(outputRoute)、输出令牌(outputToken)和输入OSS URL(inputOssUrl)。 type GetObjectContext struct { OutputRoute string `json:"outputRoute"` OutputToken string `json:"outputToken"` } // 定义StructEvent结构体,用于接收触发该函数的事件数据。 type StructEvent struct { GetObjectContext GetObjectContext `json:"getObjectContext"` } // HandleRequest函数主要用于处理计算逻辑。 func HandleRequest(ctx context.Context, event StructEvent) error { fmt.Printf("event:%#v\n", event) endpoint := event.GetObjectContext.OutputRoute fwdStatus := "200" fctx, _ := fccontext.FromContext(ctx) // 从上下文中获取访问密钥。 client, err := oss.New(endpoint, fctx.Credentials.AccessKeyId, fctx.Credentials.AccessKeySecret, oss.SecurityToken(fctx.Credentials.SecurityToken), oss.AuthVersion(oss.AuthV4), oss.Region("cn-qingdao")) if err != nil { return fmt.Errorf("client new error: %v", err) } params := map[string]interface{}{} params["x-oss-write-get-object-response"] = nil // 创建200*200像素的图片,并绘制红色的矩形框。 img := image.NewRGBA(image.Rect(0, 0, 200, 200)) red := color.RGBA{255, 0, 0, 255} draw.Draw(img, img.Bounds(), &image.Uniform{red}, image.Point{}, draw.Src) // 将图片保存为PNG格式。 var buf bytes.Buffer err = png.Encode(&buf, img) if err != nil { return fmt.Errorf("png encode error: %v", err) } reader := bytes.NewReader(buf.Bytes()) // 通过OSS客户端将转换后的图片以POST请求的形式上传,并设置了特定的HTTP头(例如x-oss-request-route),便于识别和处理特殊的转发请求。 headers := make(map[string]string) headers["x-oss-request-route"] = event.GetObjectContext.OutputRoute headers["x-oss-request-token"] = event.GetObjectContext.OutputToken headers["x-oss-fwd-status"] = fwdStatus resp, err := client.Conn.Do("POST", "", "", params, headers, reader, 0, nil) if err != nil { return fmt.Errorf("client conn do error: %v", err) } fmt.Println("status:", resp.StatusCode) fmt.Println(resp.Headers) return nil } // 启动函数计算入口点,调用fc.Start(HandleRequest)来注册并运行HandleRequest函数,等待并处理来自阿里云函数计算平台的事件触发。 func main() { fc.Start(HandleRequest) }
部署函数。
Java
自行打包.jar文件。
将.jar文件上传至函数计算控制台。
登录函数计算控制台,单击右上角返回函数计算2.0。
在左侧导航栏,单击服务及函数。
在顶部导航栏,选择华北1(青岛)地域。
在服务列表页面,单击已创建的服务,然后单击已创建的运行环境为Java 11的函数。
在函数详情页面,选择
。在弹出的对话框,选择已打包的.jar文件,勾选我想在选中文件后直接部署函数,然后单击保存并部署。
根据函数示例对应修改请求处理程序(函数入口)。
在函数详情页面,单击函数配置页签。
在环境信息区域,单击编辑。
修改请求处理程序(函数入口)。
当运行环境为Java时,当前值的格式为
[package].[class]::[method]
。如果当前值为example.HelloFC::handleRequest
,则在函数被触发时,将执行example包中HelloFC类下的handleRequest函数。您需要根据处理GetObject请求的函数示例的实际情况修改当前值,例如com.aliyun.sts.sample.Example1::handleRequest
。
Python
在服务列表页面,单击已创建的服务,然后单击已创建的运行环境为Python 3.10的函数。
在函数详情页面,单击函数代码页签,然后选择
。在TERMINAL面板,输入以下命令更新OSS Python SDK版本。
pip install oss2 -t .
将index.py中的代码示例替换为Python处理GetObject请求的函数示例,然后单击部署函数。
Go
自行安装Go SDK运行环境。
编译代码包。具体步骤,请参见编译代码包。
编译过程中,根据需求将main.go编译文件替换为上述步骤提供的需要处理GetObject请求的函数示例。
将编译生成的二进制文件以ZIP包的形式上传至已创建的运行环境为Go 1的函数,并配置函数处理程序。具体步骤,请参见配置FC函数处理程序。