使用activestorage直接上传时如何在上传到S3时指定前缀?

Mar*_*rel 9 ruby-on-rails amazon-s3 rails-activestorage ruby-on-rails-5.2

使用标准S3配置:

AWS_ACCESS_KEY_ID:        [AWS ID]
AWS_BUCKET:               [bucket name]
AWS_REGION:               [region]
AWS_SECRET_ACCESS_KEY:    [secret]
Run Code Online (Sandbox Code Playgroud)

我可以使用此Rails 5.2代码将文件上传到S3(使用直接上传)(仅显示相关代码):

form.file_field :my_asset, direct_upload: true

在提交表单后,这将有效地将我的资产置于我的S3存储桶的根目录中.

如何指定前缀(例如"development /",以便我可以模仿S3上的文件夹)?

san*_*e89 21

2022 更新:从 Rails 6.1 开始(检查此提交),实际上支持:

user.avatar.attach(key: "avatars/#{user.id}.jpg", io: io, content_type: "image/jpeg", filename: "avatar.jpg")
Run Code Online (Sandbox Code Playgroud)

  • 这应该是正确/最佳答案。 (3认同)

Geo*_*orn 6

对不起,目前还不行.我建议创建一个专门用于Active Storage的存储桶.

  • 哦,又是你。@George Claghorn这不是一个可行的选择。因此,如此之多的人都希望这样做,但我不明白为什么您只是在选择一个实际上每个竞争的图书馆都一直有能力做的选择。 (3认同)
  • 与@mpowered 一样...我只是不明白你为什么不想添加这个功能。至少给我们一个理由,而不是只说“不”。即使是 Carrierwave 也可以很容易地做到这一点。 (2认同)

Son*_*tha 6

我目前在S3上的变通方法(至少在ActiveStorage引入了为has_one_attachedand has_many_attached宏传递路径的选项之前)是实现move_to方法

因此,我让ActiveStorage像现在通常那样(在存储桶的顶部)将映像保存到S3,然后将文件移动到文件夹结构中。

move_to方法基本上将文件复制到您通过的文件夹结构中,然后删除放在存储桶根目录中的文件。这样,您的文件将最终保存在所需的位置。

因此,例如,如果我们存储驱动程序详细信息:namedrivers_license,请在保存时保存它们,以使其位于存储桶的顶部。

然后执行以下操作(我将我放在一个助手中):

        module DriversHelper

          def restructure_attachment(driver_object, new_structure)

          old_key = driver_object.image.key

          begin
            # Passing S3 Configs
            config = YAML.load_file(Rails.root.join('config', 'storage.yml'))

            s3 = Aws::S3::Resource.new(region: config['amazon']['region'],
                                       credentials: Aws::Credentials.new(config['amazon']['access_key_id'], config['amazon']['secret_access_key']))

            # Fetching the licence's Aws::S3::Object
            old_obj = s3.bucket(config['amazon']['bucket']).object(old_key)

            # Moving the license into the new folder structure
            old_obj.move_to(bucket: config['amazon']['bucket'], key: "#{new_structure}")


            update_blob_key(driver_object, new_structure)
          rescue => ex
            driver_helper_logger.error("Error restructuring license belonging to driver with id #{driver_object.id}: #{ex.full_message}")
          end
          end

          private

          # The new structure becomes the new ActiveStorage Blob key
          def update_blob_key(driver_object, new_key)
            blob = driver_object.image_attachment.blob
            begin
              blob.key = new_key
              blob.save!
            rescue => ex
              driver_helper_logger.error("Error reassigning the new key to the blob object of the driver with id #{driver_object.id}: #{ex.full_message}")
            end
          end

          def driver_helper_logger
            @driver_helper_logger ||= Logger.new("#{Rails.root}/log/driver_helper.log")
          end
        end
Run Code Online (Sandbox Code Playgroud)

重要的是更新Blob键,以使对该键的引用不会返回错误。

如果未更新密钥,则任何尝试引用该图像的功能都会在其先前位置(存储桶顶部)而不是其新位置中查找它。

文件保存后(即在create操作中),我立即从控制器中调用此函数,以使文件看起来无缝(即使不是)。

尽管这可能不是最好的方法,但它现在可以使用。

仅供参考:根据您提供的示例,new_structure变量将为new_structure = "development/#{driver_object.image.key}"

我希望这有帮助!:)