Almacenamiento de archivos utilizando Paperclip sin carga
-
13-09-2019 - |
Pregunta
Yo tenía una pregunta rápida. ¿Es posible guardar un archivo sin tener que subir a través de un formulario?
Por ejemplo, digamos que me estoy mirando archivos adjuntos de correos electrónicos, y quiero guardarlas usando un clip. ¿Cómo hago esto? ¿Tengo manualmente para llamar a un save_file (o algo similar) en algún lugar?
Cualquier ayuda sería muy apreciada!
Solución
Tengo una tarea rake que carga imágenes (logotipos del cliente) de un directorio directamente sobre parperclip. Es probable que pueda adaptarlo a sus necesidades.
Esta es mi modelo simplificado de cliente:
class Client < ActiveRecord::Base
LOGO_STYLES = {
:original => ['1024x768>', :jpg],
:medium => ['256x192#', :jpg],
:small => ['128x96#', :jpg]
}
has_attached_file :logo,
:styles => Client::LOGO_STYLES,
:url => "/clients/logo/:id.jpg?style=:style"
attr_protected :logo_file_name, :logo_content_type, :logo_size
A continuación, en mi tarea rastrillo hago esto:
# the logos are in a folder with path logos_dir
Dir.glob(File.join(logos_dir,'*')).each do |logo_path|
if File.basename(logo_path)[0]!= '.' and !File.directory? logo_path
client_code = File.basename(logo_path, '.*') #filename without extension
client = Client.find_by_code(client_code) #you could use the ids, too
raise "could not find client for client_code #{client_code}" if client.nil?
File.open(logo_path) do |f|
client.logo = f # just assign the logo attribute to a file
client.save
end #file gets closed automatically here
end
end
Saludos!
Otros consejos
El archivo guardado en Paperclip no tiene que ser cargado directamente a través de un formulario.
Estoy usando Paperclip en un proyecto para guardar archivos de direcciones URL de los resultados WebCrawler. No estoy seguro de cómo se obtendría adjuntos de correo electrónico (que están en el sistema de archivos local del servidor? ¿Es su aplicación una aplicación de correo electrónico como Gmail?) Pero siempre y cuando se puede obtener una secuencia de archivo (a través de algo así como en open(URI.parse(crawl_result))
mi caso ...) se puede adjuntar el archivo en el campo del modelo que está marcado has_attached_file
.
Este post sobre Fácil Subir a través de URL con el Paperclip me ayudó a resolver esto.
Desde ahora parece el blog original, ya no está disponible - aquí está el quid de la cuestión sacado de Wayback Machine:
Este ejemplo muestra un modelo de la foto que tiene un archivo adjunto de imagen.
La técnica que estamos utilizando requiere la adición de una columna *_remote_url
(cadena) para su fijación, que se utiliza para almacenar la URL original. Por lo tanto, en este caso, tenemos que añadir una columna denominada image_remote_url
la mesa de fotos.
# db/migrate/20081210200032_add_image_remote_url_to_photos.rb
class AddImageRemoteUrlToPhotos < ActiveRecord::Migration
def self.up
add_column :photos, :image_remote_url, :string
end
def self.down
remove_column :photos, :image_remote_url
end
end
No se requiere nada especial para el controlador ...
# app/controllers/photos_controller.rb
class PhotosController < ApplicationController
def create
@photo = Photo.new(params[:photo])
if @photo.save
redirect_to photos_path
else
render :action => 'new'
end
end
end
En la forma, añadimos una llamada text_field :image_url
, por lo que la gente puede subir un archivo o una URL ...
# app/views/photos/new.html.erb
<%= error_messages_for :photo %>
<% form_for :photo, :html => { :multipart => true } do |f| %>
Upload a photo: <%= f.file_field :image %><br>
...or provide a URL: <%= f.text_field :image_url %><br>
<%= f.submit 'Submit' %>
<% end %>
La materia carnosa está en el modelo de la foto. Necesitamos require open-uri
, añadir una attr_accessor :image_url
, y hacer las cosas normales has_attached_file
. A continuación, añadimos una devolución de llamada before_validation
para descargar el archivo en el atributo image_url
(si se proporciona) y guardar la URL original como image_remote_url
. Por último, hacemos un validates_presence_of :image_remote_url
, lo que nos permite rescatar de las muchas excepciones que pueden elevarse al intentar descargar el archivo.
# app/models/photo.rb
require 'open-uri'
class Photo < ActiveRecord::Base
attr_accessor :image_url
has_attached_file :image # etc...
before_validation :download_remote_image, :if => :image_url_provided?
validates_presence_of :image_remote_url, :if => :image_url_provided?, :message => 'is invalid or inaccessible'
private
def image_url_provided?
!self.image_url.blank?
end
def download_remote_image
self.image = do_download_remote_image
self.image_remote_url = image_url
end
def do_download_remote_image
io = open(URI.parse(image_url))
def io.original_filename; base_uri.path.split('/').last; end
io.original_filename.blank? ? nil : io
rescue # catch url errors with validations instead of exceptions (Errno::ENOENT, OpenURI::HTTPError, etc...)
end
end
Todo va a trabajar de forma normal, incluyendo la creación de miniaturas, etc. Además, puesto que estamos haciendo todas las cosas difíciles en el modelo, "subir" un archivo a través de URL funciona desde dentro de la escritura / consola, así:
$ script/console
Loading development environment (Rails 2.2.2)
>> Photo.new(:image_url => 'http://www.google.com/intl/en_ALL/images/logo.gif')
=> #<Photo image_file_name: "logo.gif", image_remote_url: "http://www.google.com/intl/en_ALL/images/logo.gif">