Forum: Italian Ruby user group Upload file semplice

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-01 17:19
Ciao a tutti,
ho creato una form per fare l'upload di un file:

<% form_for(@image, :multipart => true) do |f|  %>
    <%= f.file_field :foto %>
    <%= f.text_field :titolo %>
<% end %>

Nel database mysql ho creato un campo di tipo blob e nel controller ho
messo:

@image = Image.new(params[:image])
@image.save

Il browser sembra caricare la foto ma poi quando vado sulla vista trovo
solo il titolo e nel campo blob del database il percorso del file del
mio pc...
Dove sbaglio?
72e0b3f5418bfcf47488918109068c4c?d=identicon&s=25 Andrea Cuius (q_rails)
on 2009-05-01 17:29
(Received via mailing list)
probabilmente non hai specificato di salvare i file nel db,
sinceramente nn so che vantaggi puoi avere, io di solito li salvo come
file.
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-01 17:44
Andrea Cuius wrote:
> probabilmente non hai specificato di salvare i file nel db,
> sinceramente nn so che vantaggi puoi avere, io di solito li salvo come
> file.

Scusa la mia ingenuita'... io pensavo che con @image.save si salvassero
tutti!
Ma allora cosa devo scrivere per salvare il file nel db?
72e0b3f5418bfcf47488918109068c4c?d=identicon&s=25 Andrea Cuius (q_rails)
on 2009-05-01 17:48
(Received via mailing list)
non mi ricordo, dovresti configurarlo, sinceramente mi sa che non ho
nemmeno mai provato, ma qual' è il problema, nn puoi salvarli su file?

Q
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-01 17:50
Potrei ma come si fa?
Io vorrei che la form fosse semplice...
457cf601889947ce07fd003c28192d58?d=identicon&s=25 Cecchin Daniel (dynamic84)
on 2009-05-02 15:04
Marco Pi wrote:
> Ciao a tutti,
> ho creato una form per fare l'upload di un file:
>
> <% form_for(@image, :multipart => true) do |f|  %>
>     <%= f.file_field :foto %>
>     <%= f.text_field :titolo %>
> <% end %>
>
> Nel database mysql ho creato un campo di tipo blob e nel controller ho
> messo:
>
> @image = Image.new(params[:image])
> @image.save
>
> Il browser sembra caricare la foto ma poi quando vado sulla vista trovo
> solo il titolo e nel campo blob del database il percorso del file del
> mio pc...
> Dove sbaglio?

Ciao...
comunque nel form manca il submit che deve esser incluso tra il
form_for-end
 <% form_for(@image, :multipart => true) do |f|  %>
  <%= f.file_field :foto %>
  <%= f.text_field :titolo %>

  <%=  f.submit "Invia il file al db" %>
 <% end %>

Che metodo è del controller penso Images_controller.rb:

@image = Image.new(params[:image])
@image.save

Inserisci la struttura del database.yml

Ciao
Daniel
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-02 15:14
Sul submit hai ragione, non ho copiato bene...
Si, il metodo e' images_controller.rb
Il database ha diversi campi e un campo foto di tipo blob.
Nel file database.yml ho messo:
adapter: mysql
encoding: utf8
database: nome
username: user
password: pass
host: host
457cf601889947ce07fd003c28192d58?d=identicon&s=25 Cecchin Daniel (dynamic84)
on 2009-05-02 15:31
Marco Pi wrote:
> Sul submit hai ragione, non ho copiato bene...
> Si, il metodo e' images_controller.rb
> Il database ha diversi campi e un campo foto di tipo blob.
> Nel file database.yml ho messo:
> adapter: mysql
> encoding: utf8
> database: nome
> username: user
> password: pass
> host: host


ti manca il soket che è il percorso del tuo mysql e forse host deve aver
valore localhost se stai operando in locale... altrimenti non saprei.
Ma se ti inserisce il titolo mmmh... non saprei fai un drop dei
parametri e poi riprova a verificare se te lo inserisce...
457cf601889947ce07fd003c28192d58?d=identicon&s=25 Cecchin Daniel (dynamic84)
on 2009-05-02 15:33
Cecchin Daniel wrote:
> Marco Pi wrote:
>> Sul submit hai ragione, non ho copiato bene...
>> Si, il metodo e' images_controller.rb
>> Il database ha diversi campi e un campo foto di tipo blob.
>> Nel file database.yml ho messo:
>> adapter: mysql
>> encoding: utf8
>> database: nome
>> username: user
>> password: pass
>> host: host
>
>
> ti manca il soket che è il percorso del tuo mysql e forse host deve aver
> valore localhost se stai operando in locale... altrimenti non saprei.
> Ma se ti inserisce il titolo mmmh... non saprei fai un drop dei
> parametri e poi riprova a verificare se te lo inserisce...

Capitoooooo scusami non avevo capito bene il problema..
fammi vedere la tua views.rhtml
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-02 15:36
Il titolo lo inserisce... non capisco.
A me andrebbe bene anche salvare ll'immagine in una cartella e mettere
nel db l'url ma ho porvato in mille modi.
Il problema e' che sul mio pc funziona, sul server sul quale ho
pubblicato non va...
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-02 15:38
Ho usato questo sistema che sul mio pc funziona:
http://www.tutorialspoint.com/ruby-on-rails/rails-...
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-02 15:42
la vista e' nel primo post
457cf601889947ce07fd003c28192d58?d=identicon&s=25 Cecchin Daniel (dynamic84)
on 2009-05-02 15:46
Marco Pi wrote:
> la vista e' nel primo post

Penso che il problema sia del percorso della directory
Prova a controllare il file nel sever e verificare se c'è il file
salvato!
class DataFile < ActiveRecord::Base
  def self.save(upload)
    name =  upload['datafile'].original_filename
    directory = "public/data" ####################################<
    # create the file path
    path = File.join(directory, name)
    # write the file
    File.open(path, "wb") { |f| f.write(upload['datafile'].read) }
  end
end
457cf601889947ce07fd003c28192d58?d=identicon&s=25 Cecchin Daniel (dynamic84)
on 2009-05-02 15:51
Marco Pi wrote:
> la vista e' nel primo post

Io farei una cosa di questo genere... partendo da uno Shaffold
modificherei il model e il controller adattando il file.... sorgente che
hai quì...
Altrimenti penso che quel codice ti farà, ad un'occhiatta veloce, solo
l'aggiunta del file e non la visualizzazione... mancano dei controller..
per me.. ma non sono un espertissimo è da 6 mesi che utilizzo Ruby on
Rails
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-02 16:56
Dopo aver abbandonato l'idea di caricare le immagini in una cartella
sono tornato all'inserimento nel database e ho pensato di postare tutto
il codice (da manuale di rails) che non mi funziona ma che finalmente mi
indica un errore:
Mysql::Error: #22001Data too long for column 'foto' at row 1: INSERT
INTO `images` (`image_url`, `content_type`, ecc.).
Certo che e' strano che un campo blob non riesca a contenere una foto da
pochi k.

Il model:

class Image < ActiveRecord::Base

  validates_format_of :content_type,
                      :with => /^image/,
                      :message => "e' possibile caricare solo immagini"

  def image=(image_field)
    self.image_url = base_part_of(image_field.original_filename)
    self.content_type = image_field.content_type.chomp
    self.foto = image_field.read
  end

  def base_part_of(file_name)
    image_url = File.basename(file_name)
    image_url.gsub(/[^\w._-]/, '')
  end

end


La vista (get.html.erb):

<table>
<%=form_tag({:action => 'save'}, :multipart => true)%>
  <tr>
    <td colspan="3">
      Foto<br /><%=file_field("image","image")%>
    </td>
  </tr>
  <tr>
    <td>Titolo<br /><%=text_field :image, :titolo %></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td>Descrizione<br /><%=text_area :image, :descrizione %></td>
    <td></td>
    <td></td>
  </tr>
  <tr>
    <td colspan="3"><%= submit_tag "Salva" %></td>
  </tr>

</form>
</table>


Il controller:

class UploadController < ApplicationController

  before_filter :authorize

  def get
    @image = Image.new
  end

  def save
    @image = Image.new(params[:image])
    if @image.save
      redirect_to(:action=> "index")
    else
      render :action => "get"
    end
  end

end


La tabella del database:


images (

`id` int(11) NOT NULL auto_increment,

`titolo` varchar(100) NOT NULL,

`descrizione` text,

`image_url` varchar(200) NOT NULL,

`foto` blob,

`content_type` varchar(100) default NULL,

PRIMARY KEY  (`id`)
);
7bac9e5a826baf1d4f8a4a63bf026301?d=identicon&s=25 Michele Casari (miclab)
on 2009-05-04 09:56
Ho sentito parlar molto bene di attachment_fu, un plugin che fa al caso
tuo.

Ciao Michele.
72e0b3f5418bfcf47488918109068c4c?d=identicon&s=25 Andrea Cuius (q_rails)
on 2009-05-04 10:26
(Received via mailing list)
attachmenth_fu non si usa praticamente pìù, usa paper clip
598fadf49a8e63645edfb36cba7dc1c9?d=identicon&s=25 Luigi Maresca (luigi-s-w-net)
on 2009-05-04 14:00
Provo ad aiutarti senza l'utilizzo di nessun plugin, che poi con il
passare del tempo non funziona più. Le operazioni da fare sono 3: nel
controller, nella vista e nel model.

Nel controller definisci:

def saveimage
@book=Book.find(params[:id])
  if @book.update_attributes(params[:book])
  if @book.save
  flash[:notice]='Immagine caricata.'
  redirect_to :back
  end
  else
  flash[:notice]='Errore: Immagine non caricata.'
  redirect_to :back
  end

In una vista che sceglierai tu, generalmente è quella da cui effettui le
modifiche alla riga del db, scrivi:

<form
action="<%=url_for(:controller=>'admin',:action=>'saveimage',:id=>@book)-%>"
enctype="multipart/form-data" method="post">
<br />
<b><span style="color:red">Caricare Immagine:</span></b><br />
<input id="book_book" name="book[book]" size="30" type="file" />
<input name="commit" type="submit" value="Invia" />
</form>

Come vedi, nell'ultimo snippet, la vista fa riferimento alla tabella
book e all'item book, sembrerebbe quindi che nella tabella book esista
un item book di tipo "blob". Questo però non è vero perché l'item book è
virtuale e serve esclusivamente per richiamare il Model del "book".
Questo vuol dire che nel model del book dovrai inserire:

class Book < ActiveRecord::Base
....
def book=(book_field)
self.cover=book_field.read
end

il codice scritto ti dice che nella tabella book l'item di tipo "blob" è
cover!

Spero di esserti stato d'aiuto

Luigi
Eff93e9bbe063b7136c9b6f218071a09?d=identicon&s=25 Marco Mastrodonato (marcomd)
on 2009-05-05 15:04
Dalla mia esperienza ti posso confermare la bontà dei consigli di Luigi,
io avevo fatto qualcosa "da me" ma su filesystem. Ti consiglierei di
utilizzare questo tipo di storage che è nato per questo scopo mentre il
database per uno molto più generico quindi le prestazioni secondo me ne
risentono, anche se non ho mai fatto test in prima persona.

Se dovessi provare il filesystem ricordati di leggere a "trance" il file
per evitare di saturare il processo (specialmente se usi un host web):
File.open(path, "wb") { |f| f.write(upload['datafile'].read(4096)) }

Io ti consiglio comunque di usare un plugin per evitare inutili noie che
altri hanno già affrontato, magari più generici ma probabilmente più
accurati, questo è paperclip su database (se proprio non vuoi usare il
filesystem):
http://patshaughnessy.net/2009/2/19/database-stora...

Anche attachment_fu è un ottimo plugin, anche se con paperclip ci fai di
tutto e se non è richiesta complessità rimane più semplice e flessibile.
Io li ho usati entrambi, attachment_fu mi ha dato qualche problema di
memoria quando utilizzavo rmagick (mentre paperclip non usa questa
gemma, gestisce direttamente imagemagick) invece usato con imagescience
non ho riscontrato problemi (di default usa questo).
In definitiva, io starei su paperclip.
F741efce4573770d4054adfb42f67fc1?d=identicon&s=25 Marco Pi (marcop)
on 2009-05-09 12:01
Grazie Marco del consiglio. Ho installato Paperclip che sempbrava
semplice... non funziona.
Nel model ho messo:
has_attached_file :foto
Nella view ho messo:
<% form_for :image, :html => {:multipart => true} do |f| %>
    <%= f.titolo :titolo %>
    <%= f.file_field :foto %>
<% end %>
Nel controller ho messo:
require "paperclip"
def create
    @image = Image.create(params[:image])
end
Il fatto e' che non esce alcun errore e non capisco cosa modificare?
D716730ae3c9f3322f49d002192befc6?d=identicon&s=25 Alessandro Scolavino (ninjinka)
on 2009-05-09 19:01
sfrutto il thread, plugin che simulino un comportamento in stile svn ?
devo versionare degli allegati...
Eff93e9bbe063b7136c9b6f218071a09?d=identicon&s=25 Marco Mastrodonato (marcomd)
on 2009-05-11 11:12
Marco Pi wrote:
> Nel controller ho messo:
> require "paperclip"
> def create
>     @image = Image.create(params[:image])
> end
> Il fatto e' che non esce alcun errore e non capisco cosa modificare?

Paperclip l'hai installato come plugin? Verifica nella cartella vendor,
il require non serve.
nella create usa:
@image = Image.new(params[:image])

Verifica poi nel log l'esito dell'operazione ed eventualmente puoi
esaminare il metodo errors di image dopo la new.
This topic is locked and can not be replied to.