How to FTP in Ruby without first saving the text file
StringIO.new provides an object that acts like an opened file. It's easy to create a method like puttextfile, by using StringIO object instead of file.
require 'net/ftp'
require 'stringio'
class Net::FTP
def puttextcontent(content, remotefile, &block)
f = StringIO.new(content)
begin
storlines("STOR " + remotefile, f, &block)
ensure
f.close
end
end
end
file_content = <<filecontent
<html>
<head><title>Hello!</title></head>
<body>Hello.</body>
</html>
filecontent
ftp = Net::FTP.new(domain)
ftp.passive = true
ftp.login(username, password)
ftp.chdir(path_on_server)
ftp.puttextcontent(file_content, path_to_web_file)
ftp.close
Retrieving text file using Net::FTP without login
Login using the username "anonymous" and either "guest" or your email address as the password:
ftp = Net::FTP.new ('tgftp.nws.noaa.gov')
ftp.passive = true
ftp.login 'anonymous', 'guest'
ftp.chdir ('/data/observations/metar/stations')
...
You'll find more info about anonymous FTP here.
Download multiple FTP files like d*.txt in ruby
The simplest way would be to loop through the list of files in fileList
.
Here is an example (untested):
ftp = Net::FTP::new("ftp_server_site")
ftp.login("user", "pwd")
ftp.chdir("/RemoteDir")
fileList = ftp.list('D*.txt')
fileList.each do |file|
ftp.gettextfile(file)
end
ftp.close
Hope this helps.
Ruby converting String to File for uploading to FTP
After talking to another developer, he gave me this solution which I found to be a better for my situation, since the file did not exist already. It skips writing the string to a Tempfile and uses StringIO to upload it directly. His solution:
The Net::FTP#putbinaryfile method takes the name of a file on the local filesystem to copy to the remote filesystem. Now, if your data is in a string (and wasn't read from a file on the filesystem) then you may want to use Net::FTP#storbinary instead:
require 'stringio'
require 'net/ftp'
BLOCKSIZE = 512
data = StringIO.new("Hello, world!\n")
hostname = "ftp.domain.tld"
username = "username"
password = "password"
remote_filename = "something.txt"
Net::FTP.open(hostname, username, password) do |ftp|
# ...other ftp commands here...
ftp.storbinary("STOR #{remote_filename}", data, BLOCKSIZE)
# ...any other ftp commands...
end
The above avoids writing data that's not on disk to disk, just so you can upload it somewhere. However, if the data is already in a file on disk, you might as well just fix your code to reference its filename instead.
Rails upload file to ftp server
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
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.
And if your app is on Heroku, add this line
ftp.passive = true
Heroku's firewall setup does not allow for FTP active mode, also make sure that your FTP server supports passive mode.
Related Topics
Why Doesn't "Rails S" Work from the App Directory
Ruby - Digest::Digest Is Deprecated; Use Digest
Sinatra Clears Session on Post
Getting Uninitialized Constant Error When Trying to Run Tests
Why Does Array.Each Behavior Depend on Array.New Syntax
How to Configure Ruby to Enter the Debugger on Ctrl-C (Sigint)
Ruby Capitalize Every Word First Letter
How to Click First Link in List of Items After Upgrading to Capybara 2.0
How to Enable Tls V1.2 in Ruby? If So, How
Sinatra Configuring Environments on the Fly
Devise Login with User or Admin Models and Basecamp Style Subdomains
Use of Caret Symbol (^) in Ruby
Invalid Gemspec -Illformed Requirement ["#<Yaml::Syck::Defaultkey:0Xb5F9C990> 3.2.0"]
Howto Rank Items by Balance in Ruby on Rails