获取磁盘上 ActiveStorage 文件的路径

Posted

技术标签:

【中文标题】获取磁盘上 ActiveStorage 文件的路径【英文标题】:Get path to ActiveStorage file on disk 【发布时间】: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 获取路径或通过下载到临时文件过程似乎是选项。 【参考方案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

【讨论】:

以上是关于获取磁盘上 ActiveStorage 文件的路径的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Amazon S3 中自定义 Rails 5.2 ActiveStorage 附件的路径?

Ruby on Rails |我想从 ActiveStorage 中获取 Best Seller Taxonomy 的图像 标题已获取并显示在屏幕上,但图像不是

更改 ActiveStorage 控制器路径

FMDB databaseWithPath:不写入磁盘

django 迁移 - 从磁盘上的位置获取迁移

ActiveStorage 文件附件验证