【问题标题】:Get path to ActiveStorage file on disk获取磁盘上 ActiveStorage 文件的路径
【发布时间】:2018-10-24 16:30:27
【问题描述】:

我需要获取磁盘上使用ActiveStorage 的文件的路径。该文件存储在本地。

当我使用回形针时,我对返回完整路径的附件使用了path 方法。

例子:

user.avatar.path

查看 Active Storage Docs 时,看起来rails_blob_path 可以解决问题。在查看了它返回的内容之后,它没有提供文档的路径。因此,它返回此错误:

没有这样的文件或目录@rb_sysopen -

背景

我需要文档的路径,因为我正在使用 combine_pdf gem 来将多个 pdf 合并为一个 pdf。

对于回形针的实现,我遍历了所选 pdf 附件的 full_paths 和 load 将它们合并为组合的 pdf:

attachment_paths.each {|att_path| report << CombinePDF.load(att_path)}

【问题讨论】:

  • 文档指出,对于blob_path,“访问时,会返回到实际服务端点的重定向。这种间接将公共 URL 与实际 URL 分离”,因此通过设计,这将挫败您的身份正在做。也许使用下载选项进行调查。
  • disk service implementation 有一个名为path_for 的方法,可以满足您的需求,但它是私有的。因此,使用#send 获取路径或通过下载到临时文件过程似乎是选项。

标签: ruby-on-rails ruby rails-activestorage


【解决方案1】:

只需使用:

ActiveStorage::Blob.service.send(:path_for, user.avatar.key)

你可以在你的模型上做这样的事情:

class User < ApplicationRecord
  has_one_attached :avatar

  def avatar_on_disk
    ActiveStorage::Blob.service.send(:path_for, avatar.key)
  end
end

【讨论】:

    【解决方案2】:

    我不确定为什么所有其他答案都使用send(:url_for, key)。我正在使用 Rails 5.2.2 并且path_for 是一个公共方法,因此,最好避免使用send,或者直接调用path_for

    class User < ApplicationRecord
      has_one_attached :avatar
    
      def avatar_path
        ActiveStorage::Blob.service.path_for(avatar.key)
      end
    end
    

    值得注意的是,在视图中您可以执行以下操作:

    <p>
      <%= image_tag url_for(@user.avatar) %>
      <br>
      <%= link_to 'View', polymorphic_url(@user.avatar) %>
      <br>
      Stored at <%= @user.image_path %>
      <br>
      <%= link_to 'Download', rails_blob_path(@user.avatar, disposition: :attachment) %>
      <br>
      <%= f.file_field :avatar %>
    </p>
    

    【讨论】:

      【解决方案3】:

      感谢cmets中@muistooshort的帮助,看了Active Storage Code之后,这行得通:

      active_storage_disk_service = ActiveStorage::Service::DiskService.new(root: Rails.root.to_s + '/storage/')
      active_storage_disk_service.send(:path_for, user.avatar.blob.key)
        # => returns full path to the document stored locally on disk
      

      这个解决方案对我来说有点 hacky。我很想听听其他解决方案。不过,这对我有用。

      【讨论】:

      • 小改进ActiveStorage::Blob.service.send(:path_for, user.avatar.blob.key)
      【解决方案4】:

      您可以将附件下载到本地目录,然后进行处理。

      假设你的模型中有:

      has_one_attached :pdf_attachment
      

      你可以定义:

      def process_attachment      
         # Download the attached file in temp dir
         pdf_attachment_path = "#{Dir.tmpdir}/#{pdf_attachment.filename}"
         File.open(pdf_attachment_path, 'wb') do |file|
             file.write(pdf_attachment.download)
         end   
      
         # process the downloaded file
         # ...
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-26
        • 1970-01-01
        • 2017-02-11
        • 1970-01-01
        • 2011-04-14
        • 2011-07-22
        • 2019-09-17
        • 2012-07-17
        相关资源
        最近更新 更多