web-dev-qa-db-fra.com

Obtenir le chemin d'accès au fichier ActiveStorage sur le disque

Je dois obtenir le chemin du fichier sur le disque qui utilise ActiveStorage. Le fichier est stocké localement.

Lorsque j’utilisais Paperclip, j’utilisais la méthode path de la pièce jointe, qui renvoyait le chemin complet.

Exemple:

user.avatar.path

Tout en regardant Active Storage Docs , cela ressemblait à Rails_blob_path ferait l'affaire. Après avoir examiné ce qu'il a renvoyé, il ne fournit pas le chemin d'accès au document. Ainsi, il renvoie cette erreur:

Aucun fichier ou répertoire de ce type @ rb_sysopen -

Arrière-plan

J'ai besoin du chemin d'accès au document car j'utilise le gem combine_pdf afin de combiner plusieurs fichiers PDF en un seul fichier PDF.

Pour l'implémentation de Paperclip, j'ai itéré à travers les chemins complets des pièces jointes sélectionnées au format pdf et load dans le fichier pdf combiné:

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

Merci à l'aide de @muistooshort dans les commentaires, après avoir regardé le Code de stockage actif , cela fonctionne:

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

Cette solution me semble un peu difficile. J'aimerais entendre parler d'autres solutions. Cela fonctionne pour moi si.

9
Neil

Il suffit d'utiliser:

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

Vous pouvez faire quelque chose comme ça sur votre modèle:

class User < ApplicationRecord
  has_one_attached :avatar

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

Je ne sais pas pourquoi toutes les autres réponses utilisent send(:url_for, key). J'utilise Rails 5.2.2 et url_for est une méthode publique, il est donc préférable d'éviter send ou simplement d'appeler path_for:

class User < ApplicationRecord
  has_one_attached :avatar

  def avatar_path
    ActiveStorage::Blob.service.path_for(avatar.key)
  end
end

Il est à noter que dans la vue, vous pouvez faire des choses comme celle-ci:

<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>
7
ecoologic

Vous pouvez télécharger la pièce jointe dans un répertoire local, puis la traiter.

En supposant que vous ayez dans votre modèle:

has_one_attached :pdf_attachment

Vous pouvez définir:

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
3
ldl