对 gzip 压缩文件进行转码

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

转码和 gzip

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

Cloud Storage 不支持对 Brotli 压缩对象进行解压缩式转码。

解压缩式转码

通过解压缩式转码,您可将压缩后的文件版本存储在 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 校验和,那么防止解压缩转码会很有用。

注意事项

使用解压缩式转码时,请注意以下事项:

  • 解压缩式转码会使对响应中返回的数据进行完整性检查失效。这是因为与对象一起存储的哈希值代表压缩状态的数据,而传送的数据已移除压缩功能,因此具有不同的哈希值。如果您的数据请求者依赖校验和进行完整性检查,则您不应使用解压缩式转码。

  • 通过解压缩式转码,您可以将对象以压缩状态存储在 Cloud Storage 中,从而节省空间和费用。但是,下载对象的费用取决于其解压缩后的大小,因为这是传送对象的大小。

  • 从 Cloud Storage FUSE 装载的存储桶访问时,对象不会经过解压缩式转码,而会以压缩格式读取。

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 的对象的范围请求会按照请求执行。

后续步骤