Search code examples
rubycsvftpstringio

Ruby converting String to File for uploading to FTP


Currently we have a method that returns a string with a formatted CSV file.

string   = EXPORT.tickets

We need to upload this csv file to a ftp server like so

ftp = Net::FTP.new(server, username, password)
ftp.putbinaryfile(string)

however, the string variable is obviously a string, and not a binary file as the putbinaryfile method expects. I see two ways to do this,

  1. convert the string variable to a file first using File
  2. convert the string directly to a file with something like StringIO

Do these seem like viable options? If so, how would I approach doing this, thanks in advance!

EDIT:

Since the putbinaryfile method is looking for a file path rather than an actual file, it looks like my best best will be to create a File from the string variable. Can anyone give an example of how this can be accomplished?


Solution

  • 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.