2009-06-06 18 views
7

Simplemente quiero subir una imagen a un servidor con POST. Tan simple como suena esta tarea, parece que no hay una solución simple en Ruby.Carga de archivos de varias partes en Ruby

En mi solicitud estoy usando WWW::Mechanize para la mayoría de las cosas así que quería usarlo para esto también, y tenía una fuente de la siguiente manera:

f = File.new(filename, File::RDWR) 
reply = agent.post(
    'http://rest-test.heroku.com', 
    { 
     :pict  => f, 
     :function => 'picture2', 
     :username => @username, 
     :password => @password, 
     :pict_to => 0, 
     :pict_type => 0 
    } 
) 
f.close

Esto se traduce en un archivo totalmente basura listo en el servidor que se ve revuelto todo:

alt text http://imagehub.org/f/1tk8/garbage.png

Mi siguiente paso fue rebajar WWW :: mecanizar a versión 0.8.5. Esto funcionó hasta que intenté ejecutarlo, que falló con un error como "Módulo no encontrado en hpricot_scan.so". Utilizando la herramienta Dependency Walker pude descubrir que hpricot_scan.so necesitaba msvcrt-ruby18.dll. Sin embargo, después de poner ese .dll en mi carpeta Ruby/bin, me dio un cuadro de error vacío desde donde no pude depurar mucho más. Entonces el problema aquí es que Mechanize 0.8.5 tiene una dependencia de Hpricot en lugar de Nokogiri (que funciona perfectamente).


La siguiente idea era utilizar una gema diferente, así que traté de usar Net :: HTTP. Después de una breve investigación, pude descubrir que no hay soporte nativo para formularios multiparte en Net :: HTTP y en su lugar, tiene que crear una clase que codifique etc. para usted. Lo más útil que pude encontrar fue el Multipart-class by Stanislav Vitvitskiy. Esta clase se veía bien hasta ahora, pero no hace lo que necesito, porque no quiero publicar solo archivos, también quiero publicar datos normales, y eso no es posible con su clase.


Mi último intento fue utilizar RestClient. Esto parecía prometedor, ya que ha habido ejemplos sobre cómo cargar archivos. Sin embargo, no puedo conseguir que publique el formulario como multiparte.

f = File.new(filename, File::RDWR) 
reply = RestClient.post(
    'http://rest-test.heroku.com', 
    :pict  => f, 
    :function => 'picture2', 
    :username => @username, 
    :password => @password, 
    :pict_to => 0, 
    :pict_type => 0 
) 
f.close

estoy usando http://rest-test.heroku.com que envía de vuelta la solicitud de depurar si se envía correctamente, y siempre me sale esto de nuevo:

POST http://rest-test.heroku.com/ with a 101 byte payload, 
content type application/x-www-form-urlencoded 
{ 
    "pict" => "#<File:0x30d30c4>", 
    "username" => "s1kx", 
    "pict_to" => "0", 
    "function" => "picture2", 
    "pict_type" => "0", 
    "password" => "password" 
}

Esto muestra claramente que no utiliza multipart/form-data como contenido- escriba pero el estándar application/x-www-form-urlencoded, aunque definitivamente ve que pict es un archivo.


¿Cómo puedo subir un archivo en Ruby a un impreso de varias copias sin implementar toda la codificación de datos y alinear a mí mismo?

Respuesta

9

Problema largo, respuesta breve: Me faltaba el modo binario para leer la imagen en Windows.

f = File.new(filename, File::RDWR)

tenía que haber

f = File.new(filename, "rb")

1

Otro método es utilizar Bash y Curl. Usé este método cuando quería probar múltiples cargas de archivos.

bash_command = 'curl -v -F "[email protected],texas_reversed.png"       
http://localhost:9292/fog_upload/upload' 
command_result = `#{bash_command}` # the backticks are important <br/> 
puts command_result 
Cuestiones relacionadas