使用 Range 和 partNumber 标头 - Amazon Simple Storage Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

使用 Range 和 partNumber 标头

在 Amazon S3 对象 Lambda 中使用大型对象时,您可以使用 Range HTTP 标头从对象中下载指定的字节范围。要从相同对象中提取不同的字节范围,您可以使用到 Amazon S3 的并发连接。还可以指定 partNumber 参数(1 到 10000 之间的整数),它对于对象的指定分段执行范围内的请求。

由于您可能希望通过多种方法来处理包括 RangepartNumber 参数的请求,S3 对象 Lambda 不会将这些参数应用于转换后的对象。相反,您的 Amazon Lambda 函数必须根据应用程序的需要实施此功能。

要对 S3 对象 Lambda 使用 RangepartNumber 参数,请执行以下操作:

  • 在对象 Lambda 接入点配置中启用这些参数。

  • 编写一个 Lambda 函数,以处理包含这些参数的请求。

以下步骤介绍了如何完成此操作。

步骤 1:配置对象 Lambda 接入点

默认情况下,对象 Lambda 接入点会对在标头或查询参数中包含 RangepartNumber 参数的任何 GetObjectHeadObject 请求响应 HTTP 状态代码 501(未实施)错误。

要使对象 Lambda 接入点能够接受此类请求,您必须在对象 Lambda 接入点配置的 AllowedFeatures 部分中加入 GetObject-RangeGetObject-PartNumberHeadObject-RangeHeadObject-PartNumber。有关更新对象 Lambda 接入点配置的更多信息,请参阅创建对象 Lambda 接入点

步骤 2:在 Lambda 函数中实施 RangepartNumber 处理

当对象 Lambda 接入点使用范围内的 GetObjectHeadObject 请求调用 Lambda 函数时,RangepartNumber 参数将包含在事件上下文中。如下表所述,参数在事件上下文中的位置取决于使用的参数以及如何将其包含在对于对象 Lambda 接入点的原始请求中。

参数 事件上下文位置

Range(标头)

userRequest.headers.Range

Range(查询参数)

userRequest.url(查询参数 Range

partNumber

userRequest.url(查询参数 partNumber

重要

为对象 Lambda 接入点提供的预签名 URL 不包含原始请求中的 RangepartNumber 参数。请参阅以下选项,了解如何在函数中处理这些参数。

在您提取 RangepartNumber 值后,您可以根据应用程序的需要采取以下方法之一:

  1. 将请求的 RangepartNumber 映射到转换后的对象(建议)。

    处理 RangepartNumber 请求的最可靠方法是执行以下操作:

    • 从 Amazon S3 中检索完整的对象。

    • 转换对象。

    • 将请求的 RangepartNumber 参数应用于转换的对象。

    为此,请使用提供的预签名 URL 从 Amazon S3 获取整个对象,然后根据需要处理该对象。对于 Lambda 函数以此方式处理 Range 函数的示例,请参阅 Amazon Samples 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 参数。

    警告

    在很多情况下,向预签名 URL 应用 Range 参数将导致 Lambda 函数或发出请求的客户端出现意外行为。除非您确定应用程序在从 Amazon S3 中仅检索部分对象时能够正常工作,否则我们建议您按照前面的方法 A 中所述检索和转换完整对象。

    如果您的应用程序符合前面在方法 B 中介绍的条件,您可以简化您的 Amazon Lambda 函数,方法是仅获取所请求的对象范围,然后在该范围内运行转换。

    以下 Java 代码示例演示如何执行以下操作:

    • GetObject 请求中检索 Range 标头。

    • Range 标头添加到预签名 URL 中,Lambda 可以使用此标头从 Amazon S3 中检索请求的范围。

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