【问题标题】:CarrierWave_Direct gem: Keep current directory structure on S3CarrierWave_Direct gem:在 S3 上保留当前目录结构
【发布时间】:2013-01-25 08:17:28
【问题描述】:

所以我有一个网站已经在生产中使用carrierwave gem 存储在亚马逊s3 上的图像。我的上传者使用store_dir 方法来指定一个特定的结构来放入处理过的图像。

好吧,现在在我的开发环境中,我添加了carrierwave_direct gem 以开始直接上传到S3。问题是这个 gem 完全覆盖了我的上传器中的 store_dir 和文件名默认值。我无法实时推送我完全正常工作的上传器,因为我所有的旧图片链接都将被破坏。

据我了解,CWdirect gem 会将原始图像文件上传到 S3 上的“临时”目录,然后 S3 响应并为您提供 key 变量,以便您可以获取该文件并按照您认为合适的方式处理它。那么,我应该在carrierwave中使用一个完全独立的图像上传器类来处理图像并将它们放在正确的文件夹中吗?这意味着我将有一个专门用于carrierwave_direct 的上传器,可以上传这个gem 似乎想要上传到的任何地方;我将使用另一个链接到我的真实模型的 uploader.rb 类来保持我当前的 store_dir 和文件名结构?

无论如何,我的基本问题是,如果我已经在生产环境中运行 CW 并且具有特定文件夹结构中的图像,我该如何使用 CarrierWave_Direct gem?

【问题讨论】:

    标签: ruby-on-rails image amazon-s3 carrierwave


    【解决方案1】:

    好的,所以我确实想出了如何做到这一点,我将在下面解释。我的直觉是使用两个不同的 CarrierWave 上传器类是正确的——一个类专门用于上传到 S3(使用 CarrierWave_Direct gem),第二个类仅用于图像处理(我已经在生产中使用的类)。我会尝试在下面发布相关代码,但如果有人有问题请告诉我。我不确定为什么我没有看到其他人使用这样的单独类,但它似乎对我有用。

    我的图片上传类app\uploaders\image_uploader.rb使用carrierwave_direct gem:

    class ImageUploader < CarrierWave::Uploader::Base
      include CarrierWaveDirect::Uploader
    
      include ActiveModel::Conversion
      extend ActiveModel::Naming
    
      include CarrierWave::MimeTypes
      process :set_content_type
    
      # Add a white list of extensions which are allowed to be uploaded.
      # For images you might use something like this:
      def extension_white_list
        %w(jpg jpeg gif png)
      end
    
      # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
      include Sprockets::Helpers::RailsHelper
      include Sprockets::Helpers::IsolatedHelper
    
      # Override the directory where uploaded files will be stored.
      # CarrierWaveDirect::Uploader puts raw uploaded files in this directory on S3 as a first step
      def store_dir
        "unprocessed_uploads"
      end
    end
    

    **注意在这个类中没有进行任何处理

    我的图像处理类app\uploaders\image_processor.rb(已经在生产中使用):

    class ImageProcessor < CarrierWave::Uploader::Base
    
      # Include RMagick or MiniMagick support:
      # include CarrierWave::RMagick
      include CarrierWave::MiniMagick
      include CarrierWave::MimeTypes
      process :set_content_type
    
      # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
      include Sprockets::Helpers::RailsHelper
      include Sprockets::Helpers::IsolatedHelper
    
      # Choose what kind of storage to use for this uploader:
      storage :fog
    
      # Override the directory where uploaded files will be stored.
      # This is a sensible default for uploaders that are meant to be mounted:
      def store_dir
        "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
        # "uploads/#{model.class.to_s.underscore}/path/#{model.id}"
      end
    
      # Provide a default URL as a default if there hasn't been a file uploaded:
      def default_url
        "logos/" + [version_name, "default.png"].compact.join('_')
      end
    
      # Process files fetched from S3 after they are uploaded:
    
      def make_thumbnail(width, height)
        # uses MiniMagick classes to get a square, centered thumbnail image
        manipulate! do |img|
          if img[:width] < img[:height]
            remove = ((img[:height] - img[:width])/2).round
            img.shave("0x#{remove}")
          elsif img[:width] > img[:height]
            remove = ((img[:width] - img[:height])/2).round
            img.shave("#{remove}x0")
          end
    
          img.resize("#{width}x#{height}")
          img
        end        
      end
    
    
      # Create different versions of your uploaded files:
      # the process statement below isn't defined within a version block on purpose--this means the ORIGINAL uploaded photo is constrained to 1050 pics
      process :resize_to_limit => [1050, 1050]
      process :quality => 85 # this reduces filesize greatly and saves space
    
      version :thumb do
        process :make_thumbnail => [100, 100]
        process :quality => 85 # this reduces filesize greatly and saves space
      end
    
      version :big_thumb do
        process :make_thumbnail => [350, 350]
        process :quality => 85 # this reduces filesize greatly and saves space
      end
    
      # Add a white list of extensions which are allowed to be uploaded.
      # For images you might use something like this:
      def extension_white_list
        %w(jpg jpeg gif png)
      end
    
      # Override the filename of the uploaded files:
      # Avoid using model.id or version_name here, see uploader/store.rb for details.
      def filename
        if original_filename
          if model && model.read_attribute(:image).present?
            model.read_attribute(:image)
          else
            "#{secure_token}.#{file.extension}"
          end
        end
      end
    
    protected
      def secure_token
        var = :"@#{mounted_as}_secure_token"
        model.instance_variable_get(var) or model.instance_variable_set(var, SecureRandom.uuid)
      end
    
    end
    

    我的照片模型(总结):

    class Photo < ActiveRecord::Base
      mount_uploader :image, ImageProcessor
    
      def save_and_process_image(options = {})
        s3_unprocessed_image_url = self.image.asset_host + '/' + self.key
          # this next line downloads the image from S3
          # and this save line below will process the image and reupload to S3 according to ImageProcessor settings
          self.remote_image_url = s3_unprocessed_image_url
          save
      end
    
    end
    

    我也有可用的照片控制器和查看代码,如果你想要的话,请告诉我。基本上,我使用 ImageUploader 类将初始上传到 S3 到一个名为 unprocessed_uploads 的文件夹。然后 S3 以我传递给 ImageProcessor 类的 URL 中的 key 字段作为响应——它附加到照片并处理缩略图和其他图像,然后将它们重新上传到我在 S3 上的上传文件夹。

    这种分离意味着我在添加carrierwave_direct gem 时不需要更改我当前在S3 上的文件夹结构。希望这对其他人有帮助。如果您需要更多代码,请告诉我,我有点厌倦了打字:)

    更新——添加更多代码:

    照片控制器:

    class PhotosController < ApplicationController
    
      def index
        @photos = @photos.sort_by(&:created_at)
    
        @uploader = ImageUploader.new
        @uploader.success_action_redirect = new_tank_photo_url(@tank)
    
        respond_to do |format|
          format.html # index.html.erb
          format.json { render json: @photos }
        end
      end
    
      def create
        respond_to do |format|
    
          if @photo.save_and_process_image
            format.html { redirect_to tank_photos_path(@tank), notice: 'Photo uploaded successfully and is being processed...' }
            format.json { render json: @photo, status: :created, location: @photo }
          else
            format.html { render :new }
            format.json { render json: @photo.errors, status: :unprocessable_entity }
          end
        end
      end
    

    照片索引视图,带有上传按钮的表单:

        <%= direct_upload_form_for @uploader, :html => {:class => "form-inline"} do |f| %>
            <%= f.file_field :image %>
            <%= f.submit "Upload", :class => "btn btn-primary btn-medium" %>
        <% end %>
    

    添加上述视图/控制器代码后,这里是所采取步骤的摘要。请注意ImageUploader 类和ImageProcessor 类之间的区别:

    1. 在我的照片控制器中,我创建了属于 ImageUploader 类的 @uploader 变量——这意味着在我的索引/视图表单中提交的使用 @uploader 的图像会将图像上传到“临时”文件夹——因为它使用ImageUploader 类,则在上传此图像时(尚未)不进行任何处理。
    2. 当用户单击表单上的“上传”按钮时,会调用照片>>创建操作。此操作调用@photo.save_and_process_image - 查看模型以查看此方法实际上从 S3 的“临时”文件夹中获取最近上传的图像,对其进行处理,然后将处理后的图像重新上传到其最终目的地。这一切都是可能的,因为我的照片模型链接到 ImageProcessor 类,该类进行处理/上传。它没有链接到单独的 ImageUploader 类。

    希望这有助于解释我正在发生的事情

    【讨论】:

    • 我这里也有同样的问题,好像是CW_direct,破坏store_dir!好吧,我想知道控制器和视图是否与railscasts.com/episodes/383-uploading-to-amazon-s3 上解释的 ryan bate 相同。谢谢
    • @dcalixto,不,我不得不从这个 railscast 插曲中脱离出来。我会说一开始我有点害怕脱离,但这对我不起作用。我用这一集更好地理解了 CW 和 S3,然后不得不将我的代码更改为上面的 2 步过程,以克服 CW 破坏 store_dir 的问题。让我知道事情的进展并查看上面更新的代码。祝你好运!
    • 谢谢。太糟糕了,没有一种更简单的向后兼容方式可以从carrierwave进行升级。而且您不必在 Uploader 类中覆盖 store_dir ,对吗?默认位置很好,因为您始终可以使用 #direct_fog_url 获取 URL
    • @sfkaos 自从我查看这段代码以来已经有一段时间了,但实际上你在 S3 上有两个完全独立的上传目录。所以我相信您可以选择是否将 Uploader 类覆盖为您喜欢的任何内容,因为它与最终目标文件夹完全分开 - 这是在处理器类中指定的。
    猜你喜欢
    • 1970-01-01
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多