我第一次使用ActiveStorage。 在开发过程中一切正常,但在生产中(Heroku),我的图像无故消失了。
他们第一次显示正常,但现在没有图像显示。在控制台中,我可以看到此错误:
GET https://XXX.s3.amazonaws.com/variants/Q7MZrLyoKKmQFFwMMw9tQhPW/XXX 403 (Forbidden)
如果我尝试直接访问该URL,则会得到XML
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<X-Amz-Expires>300</X-Amz-Expires>
<Expires>2018-07-24T13:48:25Z</Expires>
<ServerTime>2018-07-24T15:25:37Z</ServerTime>
<RequestId>291D41FAC6708334</RequestId>
<HostId>lEVGuwA6Hvlm/i40PeXaje9SEBYks9+uk6DvBs=</HostId>
</Error>
这就是我的看法
<div class="cover" style="background-image: url('<%= rails_representation_path(experience.thumbnail) %>')"></div>
这就是我模型中的东西
def thumbnail
self.cover.variant(resize: "300x300").processed
end
用简单的话来说,我不希望图像过期但要一直存在。
谢谢
答案 0 :(得分:5)
ActiveStorage不支持未过期的链接。它使用到期链接(私有),并仅支持在服务上以私有形式上传文件。
这对我来说也是一个问题,仅对S3做2个补丁(警告),one simple ~30lines覆盖了ActiveStorage,使其仅适用于未到期的(公共)链接,并且another that add an acl option to has_one_attached and has_many_attached methods。
希望有帮助。
答案 1 :(得分:0)
您的问题并没有这么说,但是通常将带有CDN的AWS CloudFront等CDN与Rails应用程序结合使用。特别是在Heroku上,您可能想节省计算能力。
在这种情况下会发生什么。您照常渲染页面,并且所有图像都是从资产宿主CDN请求的,因为这是配置成集成页面的方式。它的设置可以从原始位置(也就是您的应用程序)中获取缓存中找不到的所有内容。
首先所有图像请求都通过。 ActiveStorage控制器为它们创建签名的URL,CDN继续传递它们,但也缓存它们。
现在是问题所在。默认情况下,签名的URL会在5分钟后过期,但是CDN缓存通常会更长。这是因为通常您使用摘要资产,这意味着它们不会在任何更改时按时间而是按名称失效。
解决方案很简单。 增加已签名URL的有效期,使其长于缓存的TTL 。现在,缓存会在其失效之前删除缓存的签名URL。
使用5.2中的ActiveStorage::Service.url_expires_in
或直接在初始化程序see this answer的Rails.application.config.active_storage.service_urls_expire_in
中设置URL到期。
要在CloudFront中设置缓存TTL:打开AWS控制台,选择分发,打开“行为”选项卡,向下滚动到以下字段:
然后有选择地发出无效信息,以强制重新缓存所有内容。
请记住,存在安全权衡。如果图像内容是私有的,则它们很可能不属于CDN,并且也不应该具有持久的临时URL。在这种情况下,请选择一个完全免除CDN附件的解决方案。您的应用程序将不得不承担在呈现相关页面之外对所有附加资产的URL进行签名的额外负担。
还要记住,这不一定是一个好的解决方案,而是更多的解决方法。使用上述设置,您将缓存重定向,而较重的请求将直接进入您的存储桶。 CDN的通常情况是大型媒体,而不是轻量级重定向。您确实可以减轻应用程序处理大量请求的负担。应该考虑多少是有效的优化。