使用 Range 和 partNumber 標頭 - Amazon Simple Storage Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 Range 和 partNumber 標頭

在 Amazon S3 Object Lambda 中使用大型物件時,您可以使用 Range HTTP 標頭,從物件下載指定的位元組範圍。若要從同一物件內擷取不同的位元組範圍,您可以對 Amazon S3 使用並行連線。您還可以指定 partNumber 參數 (1 到 10,000 之間的整數),其會針對物件的指定部分執行範圍請求。

因為您可能需要多種方法來處理包含 Range 或者 partNumber 參數的請求,而 S3 Object Lambda 不會將這些參數套用至轉換的物件。相反,您的 AWS Lambda 函數必須根據應用程序的需要實現此功能。

若要搭配 S3 Object Lambda 使用 RangepartNumber 參數,請執行下列動作:

  • 在 Object Lambda 存取點組態中啟用這些參數。

  • 撰寫一個 Lambda 函數,其可以處理包含這些參數的請求。

下列步驟說明如何完成這項操作。

步驟 1:設定 Object Lambda 存取點

根據預設,Object Lambda 存取點會以 HTTP 狀態碼 501 (未實作) 錯誤回應任何 GetObjectHeadObject 請求,該請求包含在標頭或查詢參數中的 RangepartNumber 參數。

若要啟用 Object Lambda 存取點以接受此類請求,您必須在 Object Lambda 存取點組態的 AllowedFeatures 區段中包括 GetObject-RangeGetObject-PartNumberHeadObject-Range 或 HeadObject-PartNumber。如需更新 Object Lambda 存取點組態的詳細資訊,請參閱 建立 Object Lambda 存取點

步驟 2:在 Lambda 函數中實作 RangepartNumber 處理

當 Object Lambda 存取點使用範圍 GetObjectHeadObject 請求叫用 Lambda 函數時,RangepartNumber 參數會包含在事件內容中。如下表所述,參數在事件內容中的位置,取決於使用的參數以及將其包含在對 Object Lambda 存取點的原始請求中的方式。

參數 事件內容位置

Range (標頭)

userRequest.headers.Range

Range (查詢參數)

userRequest.url (查詢參數 Range)

partNumber

userRequest.url (查詢參數 partNumber)

重要

針對您的 Object Lambda 存取點所提供的預先簽章 URL 不包含來自原始請求的 RangepartNumber 參數。請參閱以下有關如何在 AWS Lambda 函數中處理這些參數的選項。

在擷取 RangepartNumber 值後,您可以根據應用程式的需求採取下列其中一種方法:

  1. 將請求的 RangepartNumber 映射到轉換的物件 (建議)。

    處理 RangepartNumber 請求的最可靠方式是執行以下動作:

    • 從 Amazon S3 擷取完整物件。

    • 轉換物件。

    • 將請求的 RangepartNumber 參數套用至轉換的物件。

    為此,請使用提供的預先簽章 URL 從 Amazon S3 擷取整個物件,然後根據需要處理物件。如需以這種方式處理Range參數的 Lambda 函數範例,請參閱範例 GitHub 儲存庫中 AWS 的此範例。

  2. 將請求的 Range 映射到預先簽署的 URL。

    在某些情況下,Lambda 函數可以將請求的 Range 直接映射到預先簽署的 URL,以便從 Amazon S3 中僅擷取部分物件。只有當轉換符合以下兩個條件時,此方法才適用:

    1. 轉換函數可套用於部分物件範圍。

    2. 在轉換函數之前或之後套用 Range 參數,將會產生相同的轉換物件。

    例如,將 ASCII 編碼物件中的所有字元轉換為大寫的轉換函數滿足上述兩個條件。轉換可套用至物件的一部分,而且在轉換前與轉換後套用 Range 參數的結果相同。

    相比之下,將 ASCII 編碼物件中的字元反轉的函數不符合這些條件。這類函數滿足標準 1,因為其可以套用於部分物件範圍。但不符合標準 2,因為在轉換前套用 Range 參數與轉換後套用參數的結果不同。

    請考慮以下請求:將函數套用至包含內容 abcdefg 之物件的前三個字元。在轉換前套用 Range 參數會僅擷取 abc,接著反轉資料,傳回 cba。但是,如果在轉換之後套用參數,函數將擷取整個物件,將其反轉,然後套用 Range 參數,最終傳回 gfe。因為這些結果都不同,所以此函數不應在從 Amazon S3 擷取物件時套用 Range 參數。其反而應該擷取整個物件、執行轉換,然後才套用 Range 參數。

    警告

    在許多情況下,將 Range 參數套用至預先簽署的 URL,將導致 Lambda 函數或請求用戶端的發生意外行為。如前文方法 A 中所述,除非確定應用程式在從 Amazon S3 中僅擷取部分物件時能夠正常工作,否則建議您擷取和轉換完整物件。

    如果您的應用程式符合方法 B 先前所述的準則,您可以透過僅擷取要求的物件範圍,然後在該範圍上執行轉換,以簡化 AWS Lambda 函數。

    下列 Java 程式碼範例會示範如何執行下列動作:

    • GetObject 請求中擷取 Range 標頭。

    • Range 標頭新增至 Lambda 可以用來從 Amazon S3 擷取請求範圍的預先簽章 URL。

    private HttpRequest.Builder applyRangeHeader(ObjectLambdaEvent event, HttpRequest.Builder presignedRequest) { var header = event.getUserRequest().getHeaders().entrySet().stream() .filter(e -> e.getKey().toLowerCase(Locale.ROOT).equals("range")) .findFirst(); // Add check in the query string itself. header.ifPresent(entry -> presignedRequest.header(entry.getKey(), entry.getValue())); return presignedRequest; }