我一直试图使用Net::SFTP下载一个文件,它一直收到一个错误。
文件是部分下载的,只有2.1MB,所以它不是一个巨大的文件。我删除了文件上的循环,甚至尝试下载一个文件,得到了相同的错误:
yml = YAML.load_file Rails.root.join('config', 'ftp.yml')
Net::SFTP.start(yml["url"], yml["username"], password: yml["password"]) do |sftp|
sftp.dir.glob(File.join('users', 'import'), '*.csv').each do |f|
sftp.download!(File.join('users', 'import', f.name), Rails.root.join('processing_files', 'download_files', f.name), read_size: 1024)
end
endNoMethodError: undefined method `close' for #<Pathname:0x007fc8fdb50ea0>
from /[my_working_ap_dir]/gems/net-sftp-2.1.2/lib/net/sftp/operations/download.rb:331:in `on_read'我已经向谷歌祈祷,我已经尽我所能,也不会用它取得任何进展。
发布于 2014-07-23 21:17:18
显然,您不能使用Rails.root.join,这是造成问题的原因。但是,它确实很愚蠢,因为它会下载文件的一部分。
更改:
sftp.download!(File.join('users', 'import', f.name), Rails.root.join('processing_files', 'download_files', f.name))至:
sftp.download!(File.join('users', 'import', f.name), File.join('processing_files', 'download_files', f.name))发布于 2020-08-27 18:45:32
参数remote可以是Pathname对象,而参数local在设置时应该是String,或者是响应#write方法的对象。下面是工作代码
local_stringified_path = Rails.root.join('processing_files', f.name).to_s
sftp.download!(Pathname.new('/users/import'), local_stringified_path)对于所有好奇的人,请阅读下面的文章来理解这种行为。
NoMethodError: undefined method close' for #<Pathname:0x007fc8fdb50ea0>在#on_read方法中恰好发生这里问题,下面是相关语句的代码片段。
if response.eof?
update_progress(:close, entry)
entry.sink.close # ERRORED OUT LINE.. ideally when eof, file IO handler is supposed to be closed什么是entry.sink ?
我们已经知道#download!方法需要两个args,如下所示
sftp.download!(remote, local)给定的args remote和local被转换为条目对象这里。
[Entry.new(remote, local, recursive?)]而Entry不过是一个Struct 这里
Entry = Struct.new(:remote, :local, :directory, :size, :handle, :offset, :sink)好的,那么sink属性是什么?我们马上跳过去.
一旦打开要读取的相关远程文件,#on_open方法将使用文件处理程序这里更新此sink属性。
找到下面的片段,
entry.sink = entry.local.respond_to?(:write) ? entry.local : ::File.open(entry.local, "wb")实际上,只有当给定local #write路径对象没有实现它自己的#write方法时,Pathname对象才会发生这种情况,在我们的场景中,Pathname对象确实响应写
下面是控制台输出的一些片段,我在调试时在多个下载块调用之间进行了检查。它显示了显示上述讨论对象的entry和entry.sink。在这里,我选择了我的遥控器为Pathname对象,本地为String路径,它通过成功下载返回entry.sink和那里的适当值。
0> entry
=> #<struct Net::SFTP::Operations::Download::Entry remote=#<Pathname:214010463.xml>, local="214010463.xml", directory=nil, size=nil, handle="1", offset=32000, sink=#<File:214010463.xml>>
0> entry.sink
=> #<File:214010463.xml>https://stackoverflow.com/questions/24920056
复制相似问题