Net-SFTP: Calculando o progresso do upload

Estou escrevendo esse post, para complementar o post sobre o timeout do net-sftp, onde fiquei devendo essa a solução de calculo do progresso…

Para obter o progresso durante o upload, você precisa usar o callback do método upload! e jogar numa variável os valores do tamanho local e do tamanho do arquivo no destino.

Vejamos um pequeno exemplo, retirado da documentação:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'rubygems'
require 'net/sftp'
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
  sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
    case event
    when :open then
      # args[0] : file metadata
      puts "starting upload: #{args[0].local} -> #{args[0].remote} (#{args[0].size} bytes}"
    when :put then
      # args[0] : file metadata
      # args[1] : byte offset in remote file
      # args[2] : data being written (as string)
      puts "writing #{args[2].length} bytes to #{args[0].remote} starting at #{args[1]}"
    when :finish then
      puts "all done!"
    end
  end
end

No exemplo acima podemos verificar:

  • Ao abrir a conexão (when open), podemos chamar args[0].size e obter o tamanho total do arquivo
  • Durante a transferência (when put), ao chamar args[1] podemos obter o tamanho do arquivo remoto

Com isso, quando o tamanho total do arquivo for igual ao tamanho do arquivo remoto, então o upload estará terminado (100%). Para obter as porcentagens, basta fazer o cálculo.

Confira no exemplo abaixo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
require 'rubygems'
require 'net/sftp'
@total_size = 0
@remote_size = 0
@current_progress = 0
 
def update_sftp_progress
  progress = (@remote_size*100)/@total_size)
  if @current_progress < progress then
    @current_progress = progress
    puts "Uploading: #{@current_progress}%" 
  end
end
 
Net::SFTP.start('192.168.0.2', 'rafaelbiriba', {:password => 'teste', :timeout => 3}) do |sftp|
 sftp.upload!("/Users/rafaelbiriba/Projects/temp/video-teste-sftp.mp4", "/home/rafaelbiriba/video-teste-sftp.mp4") do |event, uploader, *args|
   case event
     when :open then
       @total_size = args[0].size
       puts "Starting upload..."
     when :put then
       @remote_size = args[1]
       update_sftp_progress
     when :finish then
       puts "Finished!"
     end
   end
end

Toda vez que o arquivo no destino for incrementado, o evento (:put) será disparado, chamando o método update_sftp_progress.

Nesse método é feito o cálculo da porcentagem(ver no exemplo acima). Ao invés de imprimir a porcentagem(com puts), você também pode salvar no banco de dados, ou utilizar o valor para fazer uma barra de progresso.

Espero ter ajudado, 😉

Share