通過對象FC存取點訪問GetObject API時,將觸發您所綁定的Function Compute服務中的函數,並在函數中配合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 } // 啟動Function Compute進入點,調用fc.Start(HandleRequest)來註冊並運行HandleRequest函數,等待並處理來自阿里雲Function Compute平台的事件觸發。 func main() { fc.Start(HandleRequest) }
部署函數。
Java
自行打包.jar檔案。
將.jar檔案上傳至Function Compute控制台。
登入Function Compute控制台,單擊右上方返回Function Compute2.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函數處理常式。