2010-04-25 22 views
12

Estoy en Rails 2.3.5 y Ruby 1.8.6 e intento descubrir cómo dejar que un usuario cargue un archivo en un servidor FTP en una máquina diferente a través de mi aplicación Rails. Además, mi aplicación Rails se alojará en Heroku, lo que no facilita la escritura de archivos en el sistema de archivos local.Archivos de carga de rieles en el servidor ftp

index.html.erb

<% form_tag '/ftp/upload', :method => :post, :multipart => true do %> 
<label for="file">File to Upload</label> <%= file_field_tag "file" %> 
<%= submit_tag 'Upload' %> 
<% end %> 

ftp_controller.rb

require 'net/ftp' 

class FtpController < ApplicationController 
    def upload 
    file = params[:file] 
    ftp = Net::FTP.new('remote-ftp-server') 
    ftp.login(user = "***", passwd = "***") 
    ftp.putbinaryfile(file.read, File.basename(file.original_filename)) 
    ftp.quit() 
    end 

    def index 
    end 

end 

Actualmente estoy tratando de obtener los rieles aplicación para trabajar en mi portátil con Windows. Con el código anterior, obtengo este error

Errno::ENOENT in FtpController#upload 
No such file or directory -.... followed by a dump of the file contents 

Estoy tratando de cargar un archivo CSV si eso hace la diferencia. ¿Alguien sabe lo que está pasando?

Respuesta

18

Después de mucha investigación y golpes de cabeza, terminé leyendo el código fuente del método putbinaryfile para encontrar una solución para la limitación de putbinaryfile. Aquí está el código de trabajo, reemplace esta línea

ftp.putbinaryfile(file.read, File.basename(file.original_filename)) 

con

ftp.storbinary("STOR " + file.original_filename, StringIO.new(file.read), Net::FTP::DEFAULT_BLOCKSIZE) 

Y en caso de que se preguntan, STOR es un comando FTP prima, sí se trataba de eso. Estoy bastante sorprendido de que este escenario no sea manejado más fácilmente por las bibliotecas estándar de Ruby, ciertamente no era obvio lo que tenía que hacerse.

Y si su aplicación está en Heroku, añada esta línea

ftp.passive = true 

configuración del firewall de Heroku no permite el modo activo de FTP, también asegurarse de que su servidor FTP soporta el modo pasivo.

+0

¿Funciona 'ftp.putbinaryfile (StringIO.new (file.read), file.original_filename, Net :: FTP :: DEFAULT_BLOCKSIZE)'? –

+0

No, eso no funcionó, arroja el error "no se puede convertir StringIO en cadena". – Bob

+0

Oye, ¿Rails 3 maneja esto mejor? – fatfrog

1

Me parece que ftp.putbinaryfile solo quiere la ruta y el nombre del archivo como primer parámetro.

+0

Esto tiene otras 2 buenas opciones: http://stackoverflow.com/questions/5223763/how-to-ftp-in-ruby-without-first-saving-the-text-file – Josh

+0

El camino es suficiente para que funcione . –