Invio di un file (http) con Ruby

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 :wink:

Qualcuno mi sa consigliare?

Grazie in anticipo,

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.
:slight_smile:
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}\

mailto:MediasController@createErrors:#{@media.errors.each{|att,msg|

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!

:slight_smile:

Facci sapere come procede, che sono curioso…


“Smaken är som baken - delad.”

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

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[email protected] 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.

Il 20/02/07, david[email protected] 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 :slight_smile:
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/

gem install curb :slight_smile:

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… :-/

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

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”)
@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”)
=> #Curl::Easy:0x33684ec
c.body_str
=> "<meta http-equiv="conten…

Cosa può essere?

Il 20/02/07, david[email protected] ha scritto:

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

http://curb.rubyforge.org/

gem install curb :slight_smile:

Ora ci gioco un po’ e vi faccio sapere…

He he… avrai risolto allora!

:slight_smile:


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

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[email protected] ha scritto: