对 gzip 压缩文件进行转码

本页面介绍如何在常规状态和 gzip 压缩状态的文件之间进行转换。在此页面中,您可以简单了解 Cloud Storage 中的转码、使用关联元数据的最佳做法以及压缩文件行为。

转码和 gzip

gzip 是一种数据压缩格式,通常用来缩减文件的大小。 与非 gzip 文件相比,gzip 文件传输得更快,并且占用的存储空间也更少。压缩文件有助于减少费用并缩短传输时间。在 Cloud Storage 中,转码是指系统在将文件传送给请求者之前自动更改文件的压缩状态。如果转码生成的文件是 gzip 压缩文件,则可视为压缩式转码,而如果转码生成的文件已不再是 gzip 压缩文件,则可视为解压缩式转码。Cloud Storage 支持解压缩形式的转码。

解压缩式转码

通过解压缩式转码,您可以在 Cloud Storage 中存储文件的压缩版本,这可以降低静态存储空间的费用,同时仍可向请求者提供文件本身,而不会进行任何压缩。例如,在向客户传送文件时,解压缩式编码会很有用。

为了进行解压缩式转码,对象必须满足以下两个条件:

  1. 文件必须以 gzip 压缩形式存储在 Cloud Storage 中。

  2. 对象的元数据包括 Content-Encoding: gzip

如果某个对象满足上述两个条件,则在传送时将会进行解压缩式转码,包含该对象的响应不会包含 Content-EncodingContent-Length 标头。

有两种方法可避免不符合其他条件的对象出现解压缩式转码:

  • 如果对该对象的请求包括 Accept-Encoding: gzip 标头,系统将在此特定请求中原样传送该对象,并包括一个 Content-Encoding: gzip 响应标头。

  • 如果该对象的 Cache-Control 元数据字段设置为 no-transform,则无论 Accept-Encoding 请求标头为何,该对象在所有后续请求中都将以压缩对象形式传送。

例如,如果您想减少出站费用或缩短时间,或者希望验证下载的对象是否具有预期的 crc32c/md5 校验和,则适合使用解压缩式转码。

Content-Type 与 Content-Encoding

为了了解 Content-TypeContent-Encoding 与转码之间的相互关联,您应该注意以下几项行为。二者都是随对象一起存储的元数据。如需有关如何向对象添加元数据的分步说明,请参阅查看和修改对象元数据

Content-Type 应包含在所有上传作业中,并指明上传对象的类型。例如:

Content-Type: text/plain

以上内容表示上传的对象是纯文本文件。系统不会执行任何检查来确保指定 Content-Type 与所上传对象的实际性质相匹配,但如果指定的对象类型不正确,这不仅会导致请求者接收不到预期内容,而且还可能引发意外行为。

Content-Encoding 是可选项;如果需要,您可在上传压缩文件时添加此项。例如:

Content-Encoding: gzip

以上内容表示上传的对象已经过 gzip 压缩。和 Content-Type 一样,系统不会执行任何检查来确保指定 Content-Encoding 实际应用于所上传的对象,因此如果指定的对象编码不正确,可能会导致后续下载请求发生意外行为。

建议做法

  • 上传 gzip 压缩对象时,建议您在设置元数据时同时指定 Content-TypeContent-Encoding 两项。例如,对于经过压缩的纯文本文件,请指定以下内容:

    Content-Type: text/plain
    Content-Encoding: gzip
    

    这项设置可让所有访问该对象的人员详细了解对象状态。此外,这样操作之后,该对象将能够在日后的下载作业中执行解压缩式转码,从而让客户端应用正确处理 Content-Type 的语义。

  • 或者,您也可以在上传对象时设置 Content-Type(以指示压缩),而不指定 Content-Encoding。例如:

    Content-Type: application/gzip
    

    但在这种情况下,请求者只能直接了解该对象已经过 gzip 压缩,而无法获取关于基础对象类型的信息。此外,该对象也将无法执行解压缩式转码。

不建议的做法

  • 尽管您在上传经过 gzip 压缩的文件时可以忽略该文件的压缩性质,但建议您不要这样做。例如,对于经过 gzip 压缩的纯文本文件,应避免仅设置 Content-Type: text/plain,以免传送给请求者的对象状态被曲解。

  • 同样,上传对象时不应忽略 Content-Type(即使包含 Content-Encoding 也是如此),否则可能会导致 Content-Type 被设置为默认值,但也可能会导致请求被拒绝,具体取决于上传方式。

错误做法

  • 设置元数据时不应以冗余方式报告对象的压缩状态:

    Content-Type: application/gzip
    Content-Encoding: gzip
    

    此设置表示,您所上传的 gzip 压缩对象已经过二次 gzip 压缩,而其实通常并非如此(如果您确实打算对某个文件进行双重压缩,请参阅下面的对压缩对象使用 gzip 部分)。如果此类报告错误的对象发生解压缩式转码,该对象在传送时将采用身份编码,但请求者会认为自己收到的对象仍然具有一个关联的压缩层。尝试解压缩该对象时,操作将会失败。

  • 同样,上传未经 gzip 压缩的文件时不应使用 Content-Encoding: gzip。否则,对象会看起来符合转码条件,但对该对象发出请求时,尝试转码的操作将会失败。

对压缩对象使用 gzip

某些对象(例如许多视频、音频和图片文件)已进行压缩处理,更不用说 gzip 文件本身了。对此类对象使用 gzip 实际上没有任何好处:在几乎所有情况下,由于 gzip 开销,这样做都会使对象变得更大。为此,通常不鼓励对已经压缩的内容使用 gzip,以防导致意外行为。

例如,尽管 Cloud Storage 允许上传和存储“双重压缩”对象(即不但对象本身已经过 gzip 压缩,而且其基础 Content-Type 本身也进行了压缩),但它不允许以双重压缩状态传送对象,除非对象的 Cache-Control 元数据包含 no-transform。Cloud Storage 会移除外部 gzip 压缩层,删除 Content-Encoding 响应标头,并传送生成的对象。即使是包含 Accept-Encoding: gzip 的请求也是如此。 因此,客户端接收的文件与上传并存储在 Cloud Storage 中的文件没有相同的校验和,于是,任何完整性检查都会失败。

使用 Range 标头

发生转码时,如果对象请求包含 Range 标头,系统则会静默地忽略该标头。这意味着针对部分内容的请求没有实现,而响应改为传送整个请求对象。例如,如果有 10 GB 对象可以进行转码,但请求中包含 Range: bytes=0-10000 标头,那么您仍会收到整个 10 GB 对象。

出现这种行为的原因在于,没有事先完整地解压缩文件,就无法从压缩文件中选择某一范围:针对部分文件内容的每个请求都将伴随着对整个文件(可能很大)的解压缩操作,这会导致资源利用率不佳。您应该了解这种行为并避免在转码时使用 Range 标头,因为传输整个对象(而不只是请求的范围)会产生费用。如需详细了解使用 Range 标头发出请求时允许的响应行为,请参阅规范

如果您需要使用 Range 标头发出请求,应确保请求的对象不会发生转码。如需实现此目标,您可以在开始上传对象时选择适当的属性。例如,对有 Content-Type: application/gzip 而没有 Content-Encoding 的对象的范围请求会按照请求执行。

后续步骤