# Invio di un file (http) con Ruby

**URL:** <https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179>\
**Category:** IT\
**Created:** [February 20, 2007, 1:34pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179 "2007-02-20T13:34:27Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 1:34pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/1 "2007-02-20T13:34:27Z")

</div>

Ciao a tutti,  
da diverse settimane sto lavorando ad una applicaizone Rails con  
ottimi risultati, ma mi trovo a daffrontare un problema per me  
totalmente nuovo: devo effettuare un POST HTTP di un file dalla mia  
applicazione ad un server remoto e mi chiedevo se c’era qualche  
libreria che mi permetta di farlo con codice di alto livello. Una  
delle mie esigenze è anche esaminare la response (il tutto ovviamente  
in modo sincrono, l’utente aspetta 😉

Qualcuno mi sa consigliare?

Grazie in anticipo,

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 2:19pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/2 "2007-02-20T14:19:33Z")

</div>

Io faccio  
così: partial:

Selezionare il file da caricare e premi _Salva_. Dimension e massima: 80Mb
 \<%= file\_field\_tag "media[data]", {:id =\> "media\_data"}%\> \<%= submit\_tag 'Salva' %\> 

model (“Media”):  
validates\_uniqueness\_of :filename,  
:on =\>:create,  
:message =\> “Un file con quel nome esiste già. Per  
sost  
ituirlo, cancellare la versione precedente e riprovare.”

controller:  
def show  
@media = Media.find params[:id]  
if @media  
send\_data @media.data, {:filename =\> @media.filename,  
type =\> @  
media.mimetype}  
logger.debug “MediasController#show Sent file  
[1]”#{@media.fil  
ename}" with size #{@media.data.length}"  
else  
logger.error “MediasController#show Could not load media  
from d  
atabase. False ID? params: #{params.inspect}”  
flash[:error] = “Impossibile reperire i dati del  
file c  
on id #{params[:id]}”  
end  
end

def create  
filedata = params[:media][:data]  
unless filedata.respond\_to?(:local\_path)  
logger.error “MediasController#create No file in there.  
#{filed  
ata.inspect}”  
flash[:error] = “Impossibile riconoscere il file  
carica  
to.”  
else  
content\_type = filedata.content\_type.chomp  
unless MimeTypes.detect{|type| type == content\_type}  
logger.error “MediasController@create Wrong  
mimetype "  
#{content\_type}"”  
flash[:error] = “Tipo di file  
"#{content\_type}  
" non riconosciuto. Impossibile caricare file.”  
else  
@media = Media.new  
params[:media  
]  
@media.podcast\_id =  
params[:podcast\_id]

```
                    @media.mimetype = content_type
                    @media.filename = 

```

filedata.original\_filen  
ame.gsub(/^.\*(\|/)/, ‘’).chomp.downcase.strip.gsub(/[^\w.-]/,'_') #  
Sanitiz  
e filename by stripping all but final part of filename (IE fix), chop  
off trail  
ing newlines and whitespace and, finally, convert non alpha-numeric  
stuff to "_  
"  
@media.data =  
filedata.sysread(fileda  
ta.length)  
old\_logger\_level, logger.level = logger.level,  
Logger::  
ERROR if logger  
saved = @media.save  
logger.level = old\_logger\_level if logger

```
                    if saved
                            logger.debug "MediasController#create 

```

SAVE was  
ok."  
flash[:notice] = “Media inserito con  
successo”  
else  
logger.error “MediasController#create  
SAVE FAIL  
ED.”  
logger.debug [2]“MediasController@create  
Errors  
: #{@media.errors.each{|att, msg| “\n\t#{att}:\t\t#{msg}”}}”  
errors = “Impossibile inserire  
nuovo med  
ia.”  
@media.errors.each{|att, msg| errors +=  
" #{msg  
}  
"}  
flash[:error] = errors  
end  
end  
end  
flash.keep  
redirect\_to :controller =\> :podcasts, :action =\> :edit, :id =\>  
params[:  
podcast\_id]  
end

migration:  
class CreateMedias \< ActiveRecord::Migration  
def self.up  
create\_table :medias do |t|  
t.column :podcast\_id, :integer  
t.column :filename, :string  
t.column :mimetype, :string  
t.column :data, :binary  
t.column :created\_at, :datetime  
t.column :updated\_at, :datetime  
end  
end

```
    def self.down
            drop_table :medias
    end

```

end

Il metodo “create” va ripulito di roba che sta molto meglio nel model  
e prima di chiudere il progetto farò un po’ di refactoring; trovo  
comodo a volte disubbedire alle regole MVC per avere tutto in un  
posto  
mentre sviluppo.  
🙂  
Ashkey wrote:

```
 Ciao a tutti,
 da diverse settimane sto lavorando ad una applicaizone Rails con
 ottimi risultati, ma mi trovo a daffrontare un problema per me
 totalmente nuovo: devo effettuare un POST HTTP di un file dalla mia
 applicazione ad un server remoto e mi chiedevo se c'era qualche
 libreria che mi permetta di farlo con codice di alto livello. Una
 delle mie esigenze è anche esaminare la response (il tutto
 ovviamente
 in modo sincrono, l'utente aspetta ;-)
 Qualcuno mi sa consigliare?
 Grazie in anticipo,

```

–  
“Den som väntar på något gott väntar inte för länge. Den som väntar på någon so  
m har gått får vänta länge. Den som har väntat för gott har väntat för länge.”

References

1. mailto:/#{@media.filename}\
2. 

[mailto:MediasController@createErrors](mailto:MediasController@createErrors):#{@media.errors.each{|att,msg|

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 3:15pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/3 "2007-02-20T15:15:41Z")

</div>

> In pratica tu salvi i dati binari di un file su DB con CREATE, mentre  
> con SHOW carichi l’immagine simulando la risposta http per un file  
> binario.

Esatto.

> Ciò che devo fare io è stabilire uan connessione HTTP tra il mio  
> server ruby/rails ed un’altro remoto inviando una REQUEST http ,  
> usando il metodo POST ed inviando diversi dati, tra cui un fiel  
> binario.

Hmm. Ok. Se il server remoto è un server web con un’interfaccia web ecc  
ti consiglio di dare un’occhiata a WWW:Mechanize; per cose non troppo  
avanzate funziona molto bene com DSL di “robot web”.

Sennò il modulo CGI, semplicemente?

O forse più performante: prepari le opzioni per curl da Ruby, poi lo  
chiami con system() o `` (backtick). Hai meno controllo forse, ma…

Se hai l’altro server sotto controllo, perché non provare con drb e un  
po’ di marshaling? Sarà ben più performante di un POST?

> Non c’è un port delle CURLIB per Ruby? Sarebbe la soluzione a tutti i  
> miei problemi… Se devo crearmi e gestirmi un socket impazzisco…

Nah, direi che ce la puoi fare anche senza socket!

🙂

Facci sapere come procede, che sono curioso…

–  
“Smaken är som baken - delad.”

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 3:02pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/4 "2007-02-20T15:02:39Z")

</div>

E’ molto interessante ma completametne diverso da quel che serve a me  
☹

In pratica tu salvi i dati binari di un file su DB con CREATE, mentre  
con SHOW carichi l’immagine simulando la risposta http per un file  
binario.

Ciò che devo fare io è stabilire uan connessione HTTP tra il mio  
server ruby/rails ed un’altro remoto inviando una REQUEST http ,  
usando il metodo POST ed inviando diversi dati, tra cui un fiel  
binario.

Non c’è un port delle CURLIB per Ruby? Sarebbe la soluzione a tutti i  
miei problemi… Se devo crearmi e gestirmi un socket impazzisco…

–  
Ashkey \< Jules Piccotti

Il 20/02/07, david[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) ha scritto:

> [CUT]
> 
> Il metodo “create” va ripulito di roba che sta molto meglio nel model  
> e prima di chiudere il progetto farò un po’ di refactoring; trovo  
> comodo a volte disubbedire alle regole MVC per avere tutto in un posto  
> mentre sviluppo.

Sindorme da PHP? Anche io ho ancora questa abitudine, ma ho visto che  
più frammento il codice in modo coerente più riesco a riutilizzarlo  
veramente.

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 3:54pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/5 "2007-02-20T15:54:00Z")

</div>

Il 20/02/07, david[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) ha scritto:

> > In pratica tu salvi i dati binari di un file su DB con CREATE, mentre  
> > con SHOW carichi l’immagine simulando la risposta http per un file  
> > binario.  
> > Hmm. Ok. Se il server remoto è un server web con un’interfaccia web ecc

Per fortuna no… Comunichiamo tramite status http e XML.

> ti consiglio di dare un’occhiata a WWW:Mechanize; per cose non troppo  
> avanzate funziona molto bene com DSL di “robot web”.

Troppo di alto livello 🙂  
Forse potrei adattarlo alle mie esigenze… ma è pensato per un uso  
diverso.  
A me basta fare il POST e poi esaminare la response.

> Sennò il modulo CGI, semplicemente?
> 
> O forse più performante: prepari le opzioni per curl da Ruby, poi lo  
> chiami con system() o `` (backtick). Hai meno controllo forse, ma…

E’ ciò che stavo valutando ma ho trovato di meglio:

[http://curb.rubyforge.org/](http://curb.rubyforge.org/)

gem install curb 🙂

Ora ci gioco un po’ e vi faccio sapere…

> Se hai l’altro server sotto controllo, perché non provare con drb e un  
> po’ di marshaling? Sarà ben più performante di un POST?

Non ho alcun controllo sull’altro server, se non concordare un xml che  
ricevo in risposta alle mie request.

Di conseguenza drb me lo sogno… :-/

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 7:03pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/6 "2007-02-20T19:03:30Z")

</div>

Sono riuscito a farlo funzionare dalla console, ed è una figata.  
Riesco ad eseguire post, get, e molte altre operazioni http senza  
problemi.

A questo indirizzo le istruzioni:  
[http://curb.rubyforge.org/files/README.html](http://curb.rubyforge.org/files/README.html)

Se lo uso in un controller Rails invece sembra darmi qualche  
problema… Ecco il codice incriminato:

require ‘curb’

class CurlController \< ApplicationController  
def test  
c = Curl::Easy.perform(“[http://www.google.co.uk](http://www.google.co.uk)”)  
@res = c.body\_str  
end  
end

Mi da l’ormai odiata eccezione:  
NoMethodError in VideosController#upload  
undefined method `perform’ for Curl::Easy:Class

Dalla console invece:

> > require ‘curb’  
> > =\> []  
> > c = Curl::Easy.perform(“[http://www.google.co.uk](http://www.google.co.uk)”)  
> > =\> #Curl::Easy:0x33684ec  
> > c.body\_str  
> > =\> "\<meta http-equiv="conten…

Cosa può essere?

Il 20/02/07, david[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) ha scritto:

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 4:07pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/7 "2007-02-20T16:07:05Z")

</div>

> E’ ciò che stavo valutando ma ho trovato di meglio:
> 
> [http://curb.rubyforge.org/](http://curb.rubyforge.org/)
> 
> gem install curb 🙂
> 
> Ora ci gioco un po’ e vi faccio sapere…

He he… avrai risolto allora!

🙂

–  
“Ce qui compte, ce n’est pas le bonheur de tout le monde, c’est le  
bonheur de chacun.” - Boris Vian

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [February 20, 2007, 7:11pm UTC](https://www.ruby-forum.com/t/invio-di-un-file-http-con-ruby/86179/8 "2007-02-20T19:11:34Z")

</div>

Ciò che mi lascia perplesso è che non ho un NameError (che ottengo se  
tolgo il require dal controller), quindi la libreria viene caricata…  
ma qualcosa non va’ come dovrebbe, dato che non vede i metodi.

Mi cheido quale sia la causa…

J

Il 20/02/07, Ashkey[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) ha scritto:
