Skip to content

Instantly share code, notes, and snippets.

@KarimP
Last active June 24, 2022 06:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save KarimP/b4855cbc08291ff754d0f75d15d4b49a to your computer and use it in GitHub Desktop.
Save KarimP/b4855cbc08291ff754d0f75d15d4b49a to your computer and use it in GitHub Desktop.
Using Ruby's Net FTP to upload a stream of partial chunks
# Simple extension of Net::FTP to allow uploading a stream instead of a file
# This allows for transferring of files between servers without downloading entire file first
# The code below is a modification of the storbinary method in Net::FTP
# https://github.com/ruby/ruby/blob/trunk/lib/net/ftp.rb#L686
# It goes without saying that the code may break at anytime and may or may not work with other
# features of Net::FTP such as using Resume.
require 'net/ftp'
class Net::FTP
#
# Puts the connection into binary (image) mode, issue a STOR command with the
# given filename and yields to the passed in block with a 'writer' lambda
# This lambda can be called with a given chunk to write to the file.
#
def putbinarystream(filename) # :yield: data
raise 'block required' unless block_given?
synchronize do
with_binary(true) do
conn = transfercmd("STOR #{filename}")
writer = lambda { |chunk| conn.write(chunk) }
yield(writer) if block_given?
conn.close
voidresp
end
end
rescue Errno::EPIPE
# EPIPE, in this case, means that the data connection was unexpectedly
# terminated. Rather than just raising EPIPE to the caller, check the
# response on the control connection. If getresp doesn't raise a more
# appropriate exception, re-raise the original exception.
getresp
raise
end
end
## SAMPLE USAGE: Transferring files between different FTP Hosts
ftp1 = Net::FTP('ftpserver1', 'user', 'password')
ftp2 = Net::FTP('ftpserver2', 'user', 'password')
ftp2.putbinarystream('file1') do |writer|
ftp1.retrbinary('RETR file1') do |chunk|
writer.call(chunk)
end
end
@jcsky
Copy link

jcsky commented Mar 13, 2019

thanks, it save my time~!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment