Rails将文件上传到ftp服务器

时间:2021-07-09 03:43:00

I'm on Rails 2.3.5 and Ruby 1.8.6 and trying to figure out how to let a user upload a file to a FTP server on a different machine via my Rails app. Also my Rails app will be hosted on Heroku which doesn't facilitate the writing of files to the local filesystem.

我正在使用Rails 2.3.5和Ruby 1.8.6并试图弄清楚如何让用户通过我的Rails应用程序将文件上传到不同机器上的FTP服务器。我的Rails应用程序也将托管在Heroku上,这不便于将文件写入本地文件系统。

index.html.erb

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

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

Currently I'm just trying to get the Rails app to work on my Windows laptop. With the above code, I'm getting this error

目前我只是想让Rails应用程序在我的Windows笔记本电脑上运行。使用上面的代码,我收到了这个错误

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

I'm trying to upload a CSV file if that makes any difference. Anyone knows what's going on?

我正在尝试上传CSV文件,如果这有任何区别。谁知道发生了什么?

2 个解决方案

#1


19  

After much research and head banging, I ended up reading the source code for putbinaryfile method to figure out a workaround for the limitation of putbinaryfile. Here's the working code, replace this line

经过大量研究和敲击后,我最终阅读了putbinaryfile方法的源代码,找出了putbinaryfile限制的解决方法。这是工作代码,替换此行

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

with

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

And in case you are wondering, STOR is a raw FTP command, yeah it came to that. I'm rather surprised this scenario isn't more easily handled by Ruby standard libraries, it certainly wasn't obvious what needed to be done.

如果你想知道,STOR是一个原始的FTP命令,是的,它来了。我很惊讶这个场景不容易被Ruby标准库处理,当然不是很明显需要做什么。

And if your app is on Heroku, add this line

如果您的应用程序在Heroku上,请添加此行

ftp.passive = true

Heroku's firewall setup does not allow for FTP active mode, also make sure that your FTP server supports passive mode.

Heroku的防火墙设置不允许FTP活动模式,也要确保您的FTP服务器支持被动模式。

#2


1  

Seems to me that ftp.putbinaryfile just wants the path and name of the file as the first parameter.

在我看来,ftp.putbinaryfile只想将文件的路径和名称作为第一个参数。

#1


19  

After much research and head banging, I ended up reading the source code for putbinaryfile method to figure out a workaround for the limitation of putbinaryfile. Here's the working code, replace this line

经过大量研究和敲击后,我最终阅读了putbinaryfile方法的源代码,找出了putbinaryfile限制的解决方法。这是工作代码,替换此行

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

with

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

And in case you are wondering, STOR is a raw FTP command, yeah it came to that. I'm rather surprised this scenario isn't more easily handled by Ruby standard libraries, it certainly wasn't obvious what needed to be done.

如果你想知道,STOR是一个原始的FTP命令,是的,它来了。我很惊讶这个场景不容易被Ruby标准库处理,当然不是很明显需要做什么。

And if your app is on Heroku, add this line

如果您的应用程序在Heroku上,请添加此行

ftp.passive = true

Heroku's firewall setup does not allow for FTP active mode, also make sure that your FTP server supports passive mode.

Heroku的防火墙设置不允许FTP活动模式,也要确保您的FTP服务器支持被动模式。

#2


1  

Seems to me that ftp.putbinaryfile just wants the path and name of the file as the first parameter.

在我看来,ftp.putbinaryfile只想将文件的路径和名称作为第一个参数。