Rails ActiveStorage:如何避免为每张图片重定向一次?

Posted

技术标签:

【中文标题】Rails ActiveStorage:如何避免为每张图片重定向一次?【英文标题】:Rails ActiveStorage: how to avoid one redirect for each image? 【发布时间】:2020-03-19 15:15:58 【问题描述】:

如果您使用 ActiveStorage 并且您有一个包含 N 个图像的页面,您会收到 N 个额外的 Rails 应用请求(即 N 个重定向)。如果一个页面上有数十张图片,这意味着会浪费大量服务器资源。

我知道重定向对签名 URL 很有用。但是我想知道为什么 Rails 不预先计算最终的签名 URL 并将其嵌入到 html 页面中......这样我们可以保持签名 URL/受保护文件的优势,而无需对 Rails 服务器进行 N 次额外调用。

是否可以直接在 HTML 中包含图像变体的最终 URL/预签名 URL(从而避免重定向)?不然怎么可能呢?

【问题讨论】:

如果您的资源通常是公开可用的,那么您可以使用public: true 配置标志。 edgeguides.rubyonrails.org/… @ekampp 你确定public: true 会避免重定向吗?我认为重定向虽然ActiveStorage::RepresentationsController 仍然存在,也适用于公众,因为它需要检查变体是否存在......你试过了吗?或者你有什么额外的参考吗? 不。不过,下面的答案会。 【参考方案1】:

经过几天的推理和测试,我对我的最终解决方案感到非常兴奋,我将在下面解释。这是一种固执己见的图像处理方法,可能并不代表当前的 Rails Way™️,但它对于提供许多公共图像的网站具有难以置信的优势,尤其是:

    当您为包含 N 张图片的页面提供服务时,您不会收到 1 + N 个对应用服务器的请求,而是只会收到 1 个对该页面的请求 图片通过 CDN 提供,这样可以缩短加载时间 存储桶并非完全公开,而是受 Cloudflare 保护 图片由 Cloudflare 缓存,大大减少您的 S3 费用 您大大减少了对 S3 的 API 请求(即存在)的数量 此解决方案不需要对 Rails 进行大的更改,因此在出现问题时可以直接切换回 Rails 的默认行为

解决办法如下:

    创建一个 s3 存储桶并将其配置为 host a public website(即称其为 storage.example.com) - 您甚至可以在存储桶级别禁用公共访问,并使用存储桶策略仅允许访问 Cloudflare ips 转到 Cloudflare 并为指向您的域的 storage.example.com 配置 CNAME;您需要使用灵活 SSL(您可以为子域使用页面规则);使用页面规则设置重缓存:设置 Cache Everything 并为 Browser Cache TTL 和 Edge Cache TTL 设置一个非常长的值(例如 1 年) 在您的 Rails 应用程序中,您可以继续使用私有存储/acl,这是默认的 Rails 行为 在每次更新或创建@post 之后,在您的Rails 应用程序中调用@post.variant(...).processed;然后在您的视图中使用'https://storage.example.com/' + @post.variant(...).key'(请注意,我们不会在视图中调用processed 以避免在s3 中进行额外检查);您还可以有一个 rake 任务,在每个对象上调用 processed,以防您需要重新生成变体;如果您只有几个不经常更改的变体(例如每个帖子 1 个图像/变体),这将非常有效

上述大部分步骤都是可选的,因此您可以根据需要将它们组合起来。

【讨论】:

您的意思是 CloudFront 而不是 Cloudflare? @Troy 我的意思是 Cloudflare:恕我直言,与 CloudFront 相比,它更强大、更便宜 抱歉 - 我对 CloudFront 的 google 研究太深了,弄糊涂了。 谢谢!这是非常彻底和有帮助的。 @collimarco 谢谢。您如何看待这种替代解决方案,它会更好吗?谢谢! dev.to/lipanski/…【参考方案2】:

您可以使用service_url 创建指向您的资源的直接链接。

我们没有在我们的项目中使用 Rails 视图,所以我对视图层的了解是生疏的。我想你可以把它放在一个专门的助手中,然后从你的视图中使用它。

【讨论】:

以上是关于Rails ActiveStorage:如何避免为每张图片重定向一次?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ActiveStorage (Rails 5.2) 中更新附件

Rails 5.2 + Trix + ActiveStorage

如何在 Rails 5.2 中复制存储在 ActiveStorage 中的文件

在 Rails 6 中使用 activestorage 时,如何在重新显示表单时保留文件?

Rails 5.2 的 ActiveStorage 图像上传错误:signed_id 委托给附件,但附件为零

如何在 Amazon S3 中自定义 Rails 5.2 ActiveStorage 附件的路径?