2015-01-21 1 views
2

В настоящее время у нас есть метод, который возвращает строку с форматированным CSV-файлом.Ruby конвертирует строку в файл для загрузки на FTP

string = EXPORT.tickets 

Нам нужно загрузить этот файл CSV на FTP-сервер, как так

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

однако, переменная string, очевидно, является строка, а не бинарный файл как метод putbinaryfile ожидает. Я вижу два способа сделать это,

  1. преобразующего переменной string в файл первого использования File
  2. преобразовать строку непосредственно в файл с чем-то вроде StringIO

ли это, кажется, как жизнеспособные варианты ? Если да, то как бы я это сделал, спасибо заранее!

EDIT:

Поскольку putbinaryfile метод ищет путь к файлу, а не фактического файла, он выглядит как мой лучший лучше будет создать файл с переменной string. Может ли кто-нибудь привести пример того, как это можно сделать?

+0

Это не 100%, 'putbinaryfile' ожидает PATH двоичного файла (который может быть строкой). Возможно, я сначала создаю файл (см. Http://devdocs.io/ruby/file#method-c-new), а затем загрузите его. Не забудьте удалить файл после его загрузки :) – mhutter

+1

Вы правы, он ищет PATH.Что вы думаете обо мне, используя класс Ruby Tempfile? http://devdocs.io/ruby/tempfile – ruevaughn

+0

Звучит неплохо! Еще одна вещь: Я ДУМАЮ, что вы можете использовать 'puttextfile' вместо' putbinaryfile', поскольку CSV - это просто текст, но обязательно проверьте это сначала ... – mhutter

ответ

4

Нечто подобное должно охватывать большинство баз:

require 'tempfile' 

temp_file = Tempfile.new('for_you') 
temp_file.write(string) 
temp_file.close 

ftp.putbinaryfile(temp_file) 

temp_file.unlink 

Используя Временный файл избавляет вас от многих проблем в отношении уникального имени файла, threadsafeness и т.д. сбора мусора обеспечит ваш файл будет удален, даже если putbinaryfile вызывает исключение или подобные опасности.

Загруженный файл получит имя как for_you.23423423.423.423.4, как локально, так и на удаленном сервере. Если вы хотите, чтобы иметь определенное имя на удаленном сервере, как «daily_log_upload», сделать это вместо того, чтобы:

ftp.putbinaryfile(temp_file, 'daily_log_upload') 

Он будет иметь уникальное имя для локального временного файла, но вы не заботитесь о том, что ,

+0

Я считаю, вы имеете в виду 'ftp.putbinaryfile (temp_file.path)', правильно? – Phrogz

+0

Я пробовал оба, и он работает в любом случае - поэтому он, очевидно, знает, как проверить, является ли это файлом objet, а также – ruevaughn

+0

Спасибо за ответ, мне также нравится решение Tempfile – ruevaughn

1

После разговора с другим разработчиком он дал мне это решение, которое, как мне показалось, было лучше для моей ситуации, поскольку файл уже не существовал. Он пропускает запись строки в Tempfile и использует StringIO для ее загрузки напрямую. Его решение:

Метод net :: FTP # putbinaryfile принимает имя файла локальной файловой системы для копирования в удаленную файловую систему. Теперь, если ваши данные в виде строки (и не были прочитаны из файла в файловой системе), то вы можете использовать Net :: FTP # storbinary вместо:

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 

Вышеприведенные избегает писать данные, которые не на диске на диск, так что вы можете загрузить его где-нибудь. Однако, если данные уже находятся в файле на диске, вы можете просто исправить свой код, чтобы ссылаться на его имя файла.

+0

Nice! Это улучшение по сравнению с Tempfile. –

Смежные вопросы