全部產品
Search
文件中心

Object Storage Service:編寫處理GetObject請求的函數

更新時間:Aug 13, 2024

通過對象FC存取點訪問GetObject API時,將觸發您所綁定的Function Compute服務中的函數,並在函數中配合WriteGetObjectResponse介面實現自訂返回資料和響應標題。

前提條件

已建立對象FC存取點。具體操作,請參見建立對象FC存取點

操作步驟

  1. 編寫處理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)
    }
  2. 部署函數。

    Java

    1. 自行打包.jar檔案。

    2. 將.jar檔案上傳至Function Compute控制台。

      1. 登入Function Compute控制台,單擊右上方返回Function Compute2.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請求的函數樣本,然後單擊部署函數

    Go

    1. 自行安裝Go SDK運行環境。

    2. 編譯程式碼封裝。具體步驟,請參見編譯程式碼封裝

      編譯過程中,根據需求將main.go編譯檔案替換為上述步驟提供的需要處理GetObject請求的函數樣本。

    3. 將編譯產生的二進位檔案以ZIP包的形式上傳至已建立的運行環境為Go 1的函數,並配置函數處理常式。具體步驟,請參見配置FC函數處理常式

後續步驟

使用對象FC存取點