View a markdown version of this page

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

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

使用 Range 和 partNumber 標頭

注意

自 2025 年 11 月 7 日起,S3 Object Lambda 僅適用於目前正在使用該服務的現有客戶,以及選取 AWS 合作夥伴網路 (APN) 合作夥伴。對於類似於 S3 Object Lambda 的功能,請在此處進一步了解 - Amazon S3 Object Lambda 可用性變更。

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

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

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

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

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

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

步驟 1:設定 Object Lambda 存取點

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

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

步驟 2:在 Lambda 函數中實作 Range 或 partNumber 處理

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

參數 事件內容位置

Range (標頭)

userRequest.headers.Range

Range (查詢參數)

userRequest.url (查詢參數 Range)

partNumber

userRequest.url (查詢參數 partNumber)

重要

針對您的 Object Lambda 存取點所提供的預先簽章 URL 不包含來自原始請求的 Range 或 partNumber 參數。請參閱下列選項,了解如何在 AWS Lambda 函數中處理這些參數。

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

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

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

    • 從 Amazon S3 擷取完整物件。

    • 轉換物件。

    • 將請求的 Range 或 partNumber 參數套用至轉換的物件。

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

  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; }