Shrine Gem Ruby on Rails无服务器图像处理程序,后台作业

我正在使用Shrine Gem通过S3分段上传处理Ruby on Rails项目中的文件。我想使用Derivatives插件作为我的派生remote_url指向一个AWS Lamdba无服务器图像处理程序,并在后台作业中处理这些派生。我已经解决了这个问题,并且有一个问题:

在上传文件后,该记录将直接与Shrine cache存储URL一起保存。后台作业完成处理并创建派生后,promote作业将attachment_url端点更新为store

因此,我想做的是首先将原始URL提升到store存储桶(这样default_url会指向store存储桶,而不是缓存),然后处理此后的衍生产品。但是,我不太清楚该怎么做。我的Shrine初始化程序和上传器在下面。

# config/initializers/shrine.rb

require 'shrine'
require 'shrine/storage/s3'
# require "shrine/storage/file_system"

s3_options = Rails.application.credentials.s3

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'cache',public: true,**s3_options),store: Shrine::Storage::S3.new(prefix: 'media',}

Shrine.plugin :activerecord           # Load active Record integration
Shrine.plugin :cached_attachment_data # For retaining cached file on form redisplays
Shrine.plugin :determine_mime_type
Shrine.plugin :infer_extension
Shrine.plugin :instrumentation
Shrine.plugin :pretty_location
Shrine.plugin :remote_url,max_size: 40*1024*1024 # ~40mb
Shrine.plugin :restore_cached_data    # Refresh metadata for cached files
Shrine.plugin :type_predicates
Shrine.plugin :uppy_s3_multipart      # Enable S3 multipart upload for Uppy https://github.com/janko/uppy-s3_multipart
Shrine.plugin :url_options,store: { host: Rails.application.credentials.asset_host } if Rails.application.credentials.asset_host.present?

# app/uploaders/file_uploader.rb

class FileUploader < Shrine
  plugin :derivatives
  plugin :default_url
  plugin :backgrounding

  # TODO: images returned by Shrine.remote_url have file extension set as .jpeg,not .jpg,which is annoying
  # TODO: set up URL fallbacks for backgrounded derivatives? https://shrinerb.com/docs/processing#url-fallbacks

  # The Cloudfront URL generated by the serverless image handler
  SERVERLESS_IMAGE_HOST = Rails.application.credentials.image_handler_host
  DEFAULT_EDITS = {
    rotate: 'auto',quality: 60,progressive: true,chromaSubsampling: '4:4:4',withoutEnlargement: true,sharpen: true
  }

  # Fall back to the original file URL when the derivative
  # https://shrinerb.com/docs/processing#url-fallbacks
  Attacher.default_url do |derivative: nil,**|
    file&.url if derivative
  end

  # Perform derivative transformations inside a background job
  Attacher.promote_block do |**options|
    if file.image?
      # TODO: the initially promoted file URL is saved to the record as the cache URL. We need to
      # promote the original image first,then perform the derivative job.
      # promote
      AttachmentDerivativeJob.perform_later(self.class.name,record.class.name,record.id,name,file_data)
    else
      promote
    end
  end

  # The derivatives plugin allows storing processed files ("derivatives") alongside the main attached file
  # https://shrinerb.com/docs/plugins/derivatives
  Attacher.derivatives do |original|
    def serverless_image_request(edits = {})
      request_path = Base64.strict_encode64({
        bucket: Shrine.storages[:cache].bucket.name,key: [Shrine.storages[:cache].prefix,record.attachment.id].reject(&:blank?).join('/'),# The aws object key of the original image in the `store` S3 bucket
        edits: edits
      }.to_json).chomp
      "#{SERVERLESS_IMAGE_HOST}/#{request_path}"
    end

    if file.image?
      process_derivatives(:image,original)
    else
      process_derivatives(:file,original)
    end
  end

  Attacher.derivatives :image do |original|
    {
      thumb: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 200,height: 200,fit: 'cover'
        }.reverse_merge(DEFAULT_EDITS)
      })),small: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 600,height: 600,fit: 'inside'
        }.reverse_merge(DEFAULT_EDITS)
      })),medium: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 1200,height: 1200,large: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 2200,height: 2200,fit: 'inside'
        }.reverse_merge(DEFAULT_EDITS)
      }))
    }
  end

  Attacher.derivatives :file do |original|
    {}
  end
end
iCMS 回答:Shrine Gem Ruby on Rails无服务器图像处理程序,后台作业

一个更新-我能够通过覆盖Attacher类中的activerecord_after_save方法来配置我的Uploader类,使其执行我想要的方式。不确定这是否是最好的解决方案,但它似乎符合我的期望。

现在,当我上传一系列图像时,它们直接上传到S3,原始文件被提升为永久神社store。在after save回调中,我触发了AttachmentDerivativeJob,该事件使用AWS Lambda的默认serverless image handler处理衍生工具的处理。

class FileUploader < Shrine
  plugin :derivatives
  plugin :default_url

  # The Cloudfront URL generated by the serverless image handler
  SERVERLESS_IMAGE_HOST = Rails.application.credentials.image_handler_host
  DEFAULT_EDITS = {
    rotate: 'auto',quality: 60,progressive: true,chromaSubsampling: '4:4:4',withoutEnlargement: true,sharpen: true
  }

  # Active Record - Overriding callbacks
  # https://shrinerb.com/docs/plugins/activerecord#overriding-callbacks
  class Attacher
    private

    def activerecord_after_save
      super

      if file.image? && derivatives.blank?
        AttachmentDerivativeJob.perform_later(self.class.name,self.record.class.name,self.record.id,self.name,self.file_data)
      end
    end
  end

  # Fall back to the original file URL when the derivative
  # https://shrinerb.com/docs/processing#url-fallbacks
  Attacher.default_url do |derivative: nil,**|
    file&.url if derivative
  end

  # The derivatives plugin allows storing processed files ("derivatives") alongside the main attached file
  # https://shrinerb.com/docs/plugins/derivatives
  Attacher.derivatives do |original|
    def serverless_image_request(edits = {})
      request_path = Base64.strict_encode64({
        bucket: Shrine.storages[:store].bucket.name,key: [Shrine.storages[:store].prefix,record.attachment.id].reject(&:blank?).join('/'),# The aws object key of the original image in the `store` S3 bucket
        edits: edits
      }.to_json).chomp
      "#{SERVERLESS_IMAGE_HOST}/#{request_path}"
    end

    if file.image?
      process_derivatives(:image,original)
    else
      process_derivatives(:file,original)
    end
  end

  Attacher.derivatives :image do |original|
    {
      thumb: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 200,height: 200,fit: 'cover'
        }.reverse_merge(DEFAULT_EDITS)
      })),small: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 600,height: 600,fit: 'inside'
        }.reverse_merge(DEFAULT_EDITS)
      })),medium: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 1200,height: 1200,large: Shrine.remote_url( serverless_image_request({
        resize: {
          width: 2200,height: 2200,fit: 'inside'
        }.reverse_merge(DEFAULT_EDITS)
      }))
    }
  end

  Attacher.derivatives :file do |original|
    {}
  end
end
本文链接:https://www.f2er.com/1950103.html

大家都在问