ruby-on-rails - 如何使用 Active Storage 保留存储空间和加载时间?

标签 ruby-on-rails file-upload google-cloud-functions google-cloud-storage rails-activestorage

我有一个包含图像的用户提交表单。最初我使用的是 Carrierwave,但是在将图像保存到谷歌云服务之前,首先将图像发送到我的服务器进行处理,如果图像/s 太大,请求超时,用户只需获取服务器错误。
所以我需要的是一种直接上传到 GCS 的方法。 Active Storage 似乎是完美的解决方案,但我对压缩的难度感到非常困惑。
理想解决方案是在上传时自动调整图像大小,但似乎没有办法做到这一点。
A 次佳 解决方案是在上传时使用类似 @record.images.first.variant(resize_to_limit [xxx,xxx]) #using image_processing gem 的内容创建调整大小的变体。 ,但文档似乎暗示只能在页面加载时创建变体,这显然对加载时间极为不利,尤其是在有很多图像的情况下。对此的更多证据是,当我创建一个变体时,它不在我的 GCS 存储桶中,因此它显然只存在于我的服务器的内存中。如果我尝试@record.images.first.variant(resize_to_limit [xxx,xxx]).service_url我得到一个网址,但它无效。当我尝试在我的网站上显示图像时,我得到一个失败的图像,当我访问 url 时,我从 GCS 收到以下错误:

The specified key does not exist. No such object.


所以显然我不能创建一个永久的网址。
A 第三个 最好的解决方案是编写一个谷歌云函数来自动调整谷歌云内部图像的大小,但要通读 docs ,看来我必须用新的 url 创建一个新的调整大小的文件,我不确定如何用数据库中的新 url 替换原始 url。
总而言之,我想要完成的是允许直接上传到 GCS,但在用户下载文件之前控制文件的大小。我对 Active Storage 的问题是 (1) 我无法控制 GCS 存储桶上文件的大小,导致任意存储成本,以及 (2) 我显然必须在用户必须下载任意大文件之间进行选择,或者必须在页面加载时处理图像,这两者在服务器成本和加载时间方面都非常昂贵。
以这种方式设置 Active Storage 似乎非常奇怪,我不禁觉得我错过了一些东西。有谁知道解决这两个问题的方法?

最佳答案

这是我为解决此问题所做的工作:
1- 我上传了用户直接添加到我的服务提供商的附件(我使用 S3)。
2- 我添加一个 after_commit调用 Sidekiq 的作业 worker 生成拇指
3- 我的 sidekiq 工作人员 ( AttachmentWorker ) 调用我模型的 generate_thumbs方法
4- generate_thumbs将循环遍历我想为此文件生成的不同大小
现在,这是棘手的部分:

def generate_thumbs
  [
    { resize: '300x300^', extent: '300x300', gravity: :center },
    { resize: '600>' }
  ].each do |size|
    self.file_url(size, true)
  end
end

def file_url(size, process = false)
  value = self.file # where file is my has_one_attached
  
  if size.nil?
    url = value
  else
    url = value.variant(size)

    if process
      url = url.processed
    end
  end

  return url.service_url
end
file_url方法,我们只会调用 .processed如果我们通过 process = true .我已经对这种方法进行了大量实验,以从中获得最佳的性能结果。.processed将检查您的存储桶是否存在该文件,如果不存在,它将生成您的新文件并上传。
另外,这是我之前问过的关于 ActiveStorage 的另一个问题,它也可以帮助您:ActiveStorage & S3: Make files public

关于ruby-on-rails - 如何使用 Active Storage 保留存储空间和加载时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62745119/

相关文章:

ruby-on-rails - 如何在 Heroku 上的 Rails 应用程序上完全关闭 Assets 编译?

javascript - 使用 PhantomJS/CasperJS 上传 JS 文件

php - 如何在 php 中传递 is_uploaded_file 检查?

android - 在通过 Google Sign In 使用 Firebase 应用程序时,如何通过 Google Cloud Function 进行身份验证?

ruby-on-rails - 使用 Ruby on Rails 设置 Leaflet

ruby-on-rails - "Access Forbidden"- 乘客,Nginx,Rails

ruby-on-rails - Rails 3 和 Heroku : automatically "rake db:migrate" on push?

symfony - "Multiple Upload"与 Symfony 3 上的 VichUploaderBundle

typescript - Firebase 模拟器缺少 tsconfig.json?

google-cloud-platform - 如何使用 sinon 、 mocha chai 模拟以下代码的响应