VB .NET -  Download de arquivos com WebClient (revisitado)


 Neste artigo eu vou mostrar como podemos baixar arquivos usando a classe WebClient usando a linguagem VB .NET.

Existem muitas formas de realizar o download de arquivos, e, uma delas, é usar a classe WebClient do namespace System.net para efetuar download e upload de arquivos na internet. Ela é uma alternativa à classe WebRequest que usamos para mostrar como fazer download via HTTP no artigo:

A classe WebClient fornece métodos para enviar dados ou receber dados de qualquer recurso identificado pela URI ; seja local , intranet ou internet.

Ela , na verdade , usa a classe WebRequest para fornecer acesso aos recursos da internet. Instâncias da classe WebClient podem acessar dados com qualquer WebRequest registrados com o método WebRequest.RegisterPrefix.

A plataforma .NET Framework suporta por padrão URIs que começam com : http , https e file:schema

A classe WebClient fornece quatro métodos para fazer o envio de arquivos para um recurso:

A classe WebClient fornece três métodos para fazer o download de arquivos a partir de um recurso:

Neste artigo vou criar uma aplicação Windows Forms usando a linguagem VB .NET para fazer o download de arquivos a partir de URI informada, salvando o arquivo em um destino especificado.

O exemplo mostra também como usar a barra de progresso para indicar o andamento do download bem como o cálculo aproximado da velocidade de download e do tempo decorrido e restante para o download.

No exemplo usado vamos usar o método DownloadFileAsync para realizar o download de forma que a thread a partir da iremos usar o método não será bloqueada.

Além disso vamos usar os controles ProgressBar, ToolTip e Timer.

Recursos usados:

Nota: Baixe e use a versão Community 2015 do VS ela é grátis e é equivalente a versão Professional.

Criando o projeto no VS Community

Abra o VS Community 2015 e clique em New Project;

Selecione a linguagem Visual Basic e o template Windows Forms Application;

Informe o nome Vbnet_Youtube e clique no botão OK;

A partir da ToolBox inclua no formulário os seguintes controles:

Disponha os controles conforme o leiaute da figura abaixo:

Agora vamos declarar os seguintes namespaces no formulário form1.vb:

Imports Microsoft.Win32

A seguir inclua o código abaixo no início do formulário form1.vb :
   'usado para configurar a uril de download
    Dim uriOrigem As Uri
    
    Dim arquivoDestino As String
    
    'Cria uma nova instância da classe WebClient
    Dim downloading As New Net.WebClient
    
    'Usada para gerenciar a API Timer para calcular a velocidade aproximada do download
    'Contém o ID do timer
    Dim timerID As IntPtr = 0
  
    'trata o valor calculado da  velocidade de download
    Dim velocidadeDownload As Integer = 0
    
    'Usado para tratar as velocidades de download maxima e media
    Dim velocidadeMaxima As Integer = 1
    Dim velocidadeMedia As Integer = 2
    
    'usadas para ajusr a calcular a velocidade média
    Dim contadorLoop As Integer = 0
    Dim contadorByte As Integer = 0
    
    ' usada para aproximar a velocidade de download
    Dim BytesAtuais As Long
    Dim BytesAnteriores As Long
    
    Dim tamanhoDownload As Long = 0
    
    'usado para fornecer o tempo decorrido desde o inicio do download
    Dim tempoInicio As Long
    Dim tempoDecorrido As TimeSpan
    
    ' tenta calcular o tempo restante
    Dim tempoRestante As TimeSpan
    Dim tempoRestanteMedia As Double

A seguir vamos definir os seguintes métodos: ( nomes dos métodos já indicam oque cada um faz)

     ' Configura o tratamento de eventos do programa
    Sub DefineTratamentoEventos()
        Try
            'pegaDownloadEmProgresso será disparada sempre que o método DownloadAsync atualizar o status do download do arquivo
            AddHandler downloading.DownloadProgressChanged, AddressOf pegaDownloadEmProgresso
            AddHandler downloading.DownloadFileCompleted, AddressOf DownloadTerminou
        
            'configura o tratmento da api timer
            AddHandler SystemEvents.TimerElapsed, AddressOf AtualizaDownload
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub
    
    'Metodo chamado quando o evento TimeElapsed quando a API Timer for executada
    Sub AtualizaDownload(ByVal sender As Object, ByVal e As Microsoft.Win32.TimerElapsedEventArgs)
        'Calcula a velocidade aproximada de download
        Try
            'total de bytes que foram processados desde a áultima vez que o valor foii checado (1 segundo atrás)
            velocidadeDownload = (BytesAtuais - BytesAnteriores)
            'Exibe o tempo que foi decorrido desde que o download iniciou
            tempoDecorrido = TimeSpan.FromTicks((Now.Ticks - tempoInicio))
            lblTempoDecorrido.Text = "Tempo Decorrido : " & String.Format("{0:00}:{1:00}:{2:00}", tempoDecorrido.TotalHours, tempoDecorrido.Minutes, tempoDecorrido.Seconds)
            If velocidadeDownload < 1 Then
                lblVelocidade.Text = "Velocidade : < 1 KB/s"
                lblVelocidadeKBits.Text = "Velocidade : < 1 Kb/s"
            Else
                'Exibe a velocidade em Kilo-BYTEs speed. 
                lblVelocidade.Text = "Velocidade : " & FormatNumber(velocidadeDownload / 1024, 2).ToString & " KB/s"
                lblVelocidadeKBits.Text = "Velocidade : " & FormatNumber((velocidadeDownload / 1024) * 8, 2).ToString & " Kb/s"
            End If
            'Numeros abaixo de 1 não vão ser exibidos
            If Not velocidadeDownload < 1 Then
                contadorLoop += 1
                contadorByte += velocidadeDownload
                velocidadeMedia = (contadorByte / contadorLoop) / 1024
                lblMedia.Text = "Média : " & FormatNumber((contadorByte / contadorLoop) / 1024, 2) & " KB/s"
            End If
            If velocidadeDownload > velocidadeMaxima Then
                velocidadeMaxima = velocidadeDownload
                lblVelocidadeMaxima.Text = "Máximo : " & FormatNumber(velocidadeMaxima / 1024, 2) & " KB/s"
            End If
            'Calcula o tempo restante para o download
            If Not velocidadeDownload < 1 Then
                tempoRestanteMedia = CDbl(tempoDecorrido.TotalSeconds / BytesAtuais)
                tempoRestante = TimeSpan.FromSeconds(tempoRestanteMedia * (tamanhoDownload - BytesAtuais))
                lblTempoRestante.Text = "Tempo Restante : " & String.Format("{0:00}:{1:00}:{2:00}", tempoRestante.TotalHours, tempoRestante.Minutes, tempoRestante.Seconds)
            End If
            'mantem o valor anterior para recalcular  velocidade quando o time alcança 1 segundo novamente
            BytesAnteriores = BytesAtuais
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    'Esta sub contém o código que faz o download
    Sub FazDownload()
        Try
            arquivoDestino = txtDestinoDownload.Text
            'Usando a versão Assincrona do método DownloadFile your applications thread won't be focused on the 
            downloading.DownloadFileAsync(uriOrigem, arquivoDestino)
            btnCancelarDownload.Enabled = True
            btnIniciarDownload.Enabled = False
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    'É disparada quando o download terminar
    Sub DownloadTerminou(ByVal sender As Object, ByVal e As System.ComponentModel.AsyncCompletedEventArgs)
        Try
            If e.Cancelled Then
                lblStatus.Text = "Status: Cancelado."
                btnAbrirArquivo.Enabled = False
            Else
                lblStatus.Text = "Status: Concluído !"
                btnAbrirArquivo.Enabled = True
            End If
            btnCancelarDownload.Enabled = False
            btnIniciarDownload.Enabled = True
            
            If timerID.ToInt32 > 0 Then
                SystemEvents.KillTimer(timerID)
                timerID = Nothing
            End If
        Catch exc As Exception
            MessageBox.Show(e.Error.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    'Será disparada quando o evento DownloadProgress atuar
    Sub pegaDownloadEmProgresso(ByVal sender As Object, ByVal e As System.Net.DownloadProgressChangedEventArgs)
        Try
            'atualiza o percental da progressbar
            pgbarDownload.Value = e.ProgressPercentage
            lblProgresso.Text = "Progresso : " & e.ProgressPercentage.ToString & "%"
            tamanhoDownload = e.TotalBytesToReceive
            lblBaixados.Text = "Baixados : " & FormatNumber(e.BytesReceived / 1024, 2).ToString & " KB"
            lblTamanho.Text = "Tamanho  : " & FormatNumber(e.TotalBytesToReceive / 1024, 2).ToString & " KB"
            BytesAtuais = e.BytesReceived
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

Para concluir vamos definir o código dos eventos Click dos botões de comando e dos eventos Load e FormClosing do formulário :

  Private Sub btnDownload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIniciarDownload.Click
        Try
            'limpa os valores
            BytesAtuais = 0
            BytesAnteriores = 0
            velocidadeDownload = 0
            velocidadeMaxima = 0
            velocidadeMedia = 0
            contadorLoop = 0
            contadorByte = 0
            pgbarDownload.Value = 0
           
            'Define um novo Uniform Resource Identifier.
            uriOrigem = New Uri(txtOrigemDownload.Text)
            
            ' é feito uma Ping no host antes do Download
            lblPingHost.Text = "Ping Host: " & My.Computer.Network.Ping(uriOrigem.Host)
            'Inicia o timer para a cada segundo pegar o id o qual esta sendo usado quando for matar o timer
            timerID = SystemEvents.CreateTimer((1000))
            FazDownload()
            tempoInicio = Now.Ticks
            lblStatus.Text = "Status: Iniciado."
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Download !", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    'método para cancelar o download
    Private Sub btnCancelarDownload_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancelarDownload.Click
        Try
            If timerID.ToInt32 > 0 Then
                SystemEvents.KillTimer(timerID)
                timerID = Nothing
            End If
            downloading.CancelAsync()
            lblPingHost.Text = "Ping Host: n/a"
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

     'Abre o diálogo SaveDialog para o usuário selecionar um local de destino para o download
    Private Sub btnProcurar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcurar.Click
        Dim saveDLG As New SaveFileDialog
        Dim ext As String = "|Exe(*.exe)|*.exe"
        saveDLG.Filter = "Todos Arqs. (*.*)|*.*" & ext '"Exe (*.exe)|*.exe"
        saveDLG.Title = "Selecione o caminho e nome do arquivo para salvar o arquivo baixado." & vbNewLine & vbNewLine & "Inclua a extensão do arquivo."
        If saveDLG.ShowDialog = Windows.Forms.DialogResult.OK Then
            txtDestinoDownload.Text = saveDLG.FileName
        End If
    End Sub

    Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        If downloading.IsBusy Then
            btnCancelarDownload.PerformClick()
        End If
    End Sub

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Try
            DefineTratamentoEventos()
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    Private Sub btnAbrirArquivo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAbrirArquivo.Click
        Try
            'Tenta executar o arquivo que foi baixado
            If My.Computer.FileSystem.FileExists(txtDestinoDownload.Text) Then
                Process.Start(txtDestinoDownload.Text)
            Else
                MessageBox.Show("O arquivo indicado parece que não exite no lcoal de destino." & vbNewLine &
                    vbNewLine & "Verifique se o arquivo foi baixado e salvo com sucesso.", " Arquivo não pode ser aberto", MessageBoxButtons.OK, MessageBoxIcon.Error)
            End If
        Catch exc As Exception
            MessageBox.Show(exc.Message, "  Info!", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End Try
    End Sub

    Private Sub btnLimpar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLimpar.Click
        txtOrigemDownload.Clear()
        txtOrigemDownload.Paste(Clipboard.GetText)
    End Sub

    Private Sub btnEncerrar_Click(sender As System.Object, e As System.EventArgs) Handles btnEncerrar.Click
        'descarrega os formuláros e recurso da aplicação
        btnCancelarDownload.PerformClick()
        Application.Exit()
    End Sub

Executando o projeto iremos obter:

Pegue o projeto completo aqui :    Download_Arquivos.zip

Na verdade, na verdade vos digo que quem ouve a minha palavra, e crê naquele que me enviou, tem a vida eterna, e não entrará em condenação, mas passou da morte para a vida.
João 5:24

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?


  Gostou
?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti