16

对于我的 Web 应用程序中的 JPEG 图像传输,我正在考虑使用 Amazon S3(或 Amazon Cloudfront,如果它被证明是更好的选择)但有两个可能相反的要求:

  1. 图片是私人内容;我想使用过期时间短的签名 URL。
  2. 图像很大;我希望它们被用户的浏览器长期缓存。

我正在考虑的方法是:

  1. 用户请求 www.myserver.com/the_image
  2. 我服务器上的逻辑确定允许用户查看图像。如果他们被允许...
  3. 将浏览器 ( ) 重定向is HTTP 307 best ?到签名的 Cloudfront URL
  4. 签名的 Cloudfront URL 在 60 秒后过期,但其响应包括“ Cache-Control max-age=31536000, private

我预见的问题是,下次加载页面时,浏览器将寻找 www.myserver.com/the_image 但其缓存将用于已签名的 Cloudfront URL。由于过期时间非常短,我的服务器将第二次返回一个不同的签名 Cloudfront URL,因此浏览器不会知道它可以使用它的缓存。

有没有办法让我的网络服务器代理来自 Cloudfront 的图像(这显然否定了使用 Cloudfront 的所有好处)?

想知道是否有一些我可以做etagHTTP 304不能完全加入这些点的事情......

4

3 回答 3

10

总而言之,您有想要通过 Amazon Cloudfront 通过签名 url 提供的私有图像,并且到期时间很短。然而,虽然通过特定 url 的访问可能是有时间限制的,但即使在 url 过期之后,客户端仍希望在后续请求中从缓存中提供图像。

无论客户端如何到达云端 url(直接或通过某些服务器重定向),图像的客户端缓存将仅与用于请求图像的特定 url 相关联(而不是任何其他 url)。

例如,假设您的签名网址如下(出于示例目的缩短了到期时间戳):

http://[domain].cloudfront.net/image.jpg?Expires=1000&Signature=[Signature]

如果您希望客户端从缓存中受益,则必须将其发送到相同的 url。例如,您不能将客户端定向到以下 url 并期望客户端使用来自第一个 url 的缓存响应:

http://[domain].cloudfront.net/image.jpg?Expires=5000&Signature=[Signature]

目前还没有缓存控制机制来解决这个问题,包括 ETag、Vary 等。 web 上客户端缓存的本质是缓存中的一个资源与一个 url 相关联,其他机制的目的是帮助客户端确定由特定 url 标识的资源的缓存版本何时仍然是新鲜的。

因此,您陷入了这样一种情况,即为了从缓存响应中受益,您必须将客户端发送到与第一个请求相同的 url。有可能实现这一点的方法(cookie、本地存储、服务器脚本等),假设您已经实现了一种。

接下来您必须考虑缓存只是一个建议,即使这样也不是保证。如果您希望客户端缓存图像并将原始 url 提供给它以从缓存中受益,那么您将面临缓存未命中的风险。如果在 url 过期时间后缓存未命中,则原始 url 不再有效。然后客户端无法显示图像(来自缓存或提供的 url)。

当到期时间在 url 中时,您正在寻找的行为根本无法通过常规缓存提供。

由于无法实现所需的行为,您可能会考虑下一个最佳选项,其中每个选项都需要放弃您需求的一个方面。按照我考虑的顺序:

  1. 如果您放弃较短的到期时间,您可以使用更长的到期时间并轮换网址。例如,您可以将 url 到期时间设置为午夜,然后为当天的所有请求提供相同的 url。您的客户将受益于当天的缓存,这可能总比没有好。明显的缺点是您的网址的有效期更长。

  2. 如果您放弃内容交付,您可以从服务器提供图像,该服务器检查每个请求的访问权限。客户端将能够根据需要缓存资源,这可能比内容交付更好,具体取决于缓存命中的频率。一种变体是将 Amazon CloudFront 换成另一个提供商,因为可能有其他支持这种行为的内容交付网络(尽管我不知道有)。根据您的特定访问者,内容交付网络的丢失可能是不利的,也可能无关紧要。

  3. 如果您放弃单个静态 HTTP 请求的简单性,您可以使用客户端脚本来确定应该发出的请求。例如,在 javascript 中,您可以尝试使用原始 url 检索资源(以从缓存中受益),如果失败(由于缓存未命中和过期过期)请求新的 url 用于资源。一种变体是使用浏览器缓存以外的一些缓存机制,例如本地存储。这里的缺点是增加了浏览器预取的复杂性和受损的能力。

于 2014-12-16T01:29:48.017 回答
-1

看来你已经解决了这个问题。您说您的服务器正在向http 307云端 URL(签名 URL)发出重定向,因此浏览器仅缓存云端 URL 而不是您的 URL(www.myserver.com/the_image)。所以场景如下:客户端 1 检查 www.myserver.com/the_image -> 被重定向到 CloudFront URL -> 内容被缓存 CloudFront url 现在过期。

客户端 1 再次检查 www.myserver.com/the_image -> 被重定向到相同的 CloudFront URL-> 从缓存中检索内容,而无需再次获取云端内容。

客户端 2 检查 www.myserver.com/the_image -> 被重定向到 CloudFront URL,该 URL 由于签名过期而拒绝其访问。

于 2014-12-12T21:52:16.507 回答
-1

保存用户+图像+到期时间的列表 -> 云端链接。如果用户有未过期的云端链接,请将其用于图像并且不要生成新的。

于 2013-02-05T14:36:11.493 回答