Pearware Blog : Archives for June 2007 http://blog.pearware.org/articles/2007/06.rss en-us 40 agile web development Reworking Net::SFTP to handle large file downloads <p>I&#8217;m writing an application that downloads access logs from our production servers and runs the <a href="http://awstats.sourceforge.net">AWStats</a> package against them to create the statistics web pages. This process is setup as a Rake task that uses the Net::SFTP library used by <a href="http://www.capify.org">Capistrano</a>, written by Jamis Buck. There is also a front-end Rails application to manage each of the applications to be retrieved. Everything was working great until I tried to grab a 550MB file from one of our servers. Net::SFTP chocked as it ran out of memory.</p> <p>It turns out that the command:</p> <pre><code> sftp.get_file log_file, local_file</code></pre> <p>ends up putting the whole file into memory, which is fine for small files, but not the large one that I was trying to download. Luckily it wasn&#8217;t too bad to refactor my class. Here&#8217;s the new code to achieve the same effect as the above <em>sftp.get_file</em> command.</p> <div class="typocode"><pre><code class="typocode_default "> stat = sftp.stat( log_file ) offset = 0 file_length = stat.size length = 64 * 1024 * 1024 File.open(local_file, File::CREAT|File::TRUNC|File::RDWR, 0644) do |f| while (offset &amp;lt; file_length) sftp.open_handle(log_file) do |handle| data = sftp.read(handle, :length =&amp;gt; length, :offset =&amp;gt; offset) f.write(data) offset += data.length end end end</code></pre></div> <p>This downloads the file in 64MB increments, using only that much memory at any time.</p> Tue, 26 Jun 2007 14:13:00 -0500 urn:uuid:ec2657e4-c48c-4060-aa19-59894f59df7c http://blog.pearware.org/articles/2007/06/26/reworking-net-sftp-to-handle-large-file-downloads#comments ruby rails ruby rails capistrano net::sftp rake http://blog.pearware.org/articles/2007/06/26/reworking-net-sftp-to-handle-large-file-downloads