ASP .NET - Acesso seguro com download de arquivos na web - 2


O objetivo deste artigo é mostrar como criar uma aplicação ASP .NET que tenha as seguintes funcionalidades:

Na primeira parte concluímos a primeira funcionalidade criando a estrutura e a página de login para o web site.

Nesta segunda parte irei exibir os arquivos para download na página Download.aspx e permitir que o usuário efetue o download do arquivo.

Para realizar essa tarefa vou usar as classes Directory e FileInfo para obter as informações e apresentar os nomes dos arquivos que desejamos tornar disponíveis para o usuário.

Vamos exibir os nomes dos arquivos em um controle ListBox(ID=lstArquivos) na página Download.aspx e usando um controle Button(ID=btnDownload) para iniciar o download do arquivo.

Quando o usuário clicar no botão iremos gerar um stream para o navegador permitindo assim o download do arquivo.

O leiaute da página Download.aspx é mostrado a seguir:

No arquivo code-behind Default.aspx.vb vamos usar criar o código usando a linguagem Visual Basic para realizar as seguintes tarefas:

  1. Criar uma lista de arquivos disponíveis para download usando o método GetFiles da classe Directory;
  2. Preencher o controle ListBox com os nomes dos arquivos ;
  3. Processar o download do arquivo gerando um stream do arquivo selecionado para o navegador usando o objeto Response;

Antes de partir para o código vamos criar uma nova pasta no web site chamada Imagens.

Clique com o botão direito do mouse sobre o nome do web site e selecione New Folder e digite o nome Imagens.

A seguir vamos incluir algumas imagens nesta pasta clicando com o botão direito sobre ela e selecionando a opção Add Existing Item e inclua algumas imagens conforme a figura abaixo:

Agora vamos ao código...

Abra o arquivo Download.aspx.vb e declare no início do arquivo o seguinte namespace:

Imports System.IO

No evento Load do formulário vamos definir o código abaixo:

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim arquivos() As String
        Dim index As Integer

        If (Not Page.IsPostBack) Then
            'obtem uma lista dos arquivos das imagens no diretorio de exemplo
            arquivos = Directory.GetFiles(Server.MapPath("Imagens"))

            'para exibir os arquivos vamos remover o caminho
            For index = 0 To arquivos.Length - 1
                arquivos(index) = New FileInfo(arquivos(index)).Name
            Next index

            'vincula a lista de arquivos ao ListBox
            lstArquivos.DataSource = arquivos
            lstArquivos.DataBind()

            'seleciona a primeira entrada da lista
            lstArquivos.SelectedIndex = 0
        End If

    End Sub

Este código preenche um array de strings com os nomes dos arquivos obtidos da pasta Imagens exibindo os nomes das imagens no controle ListBox;

Quando o usuário selecionar um arquivo e clicar no botão Download devemos permitir o dowload do arquivo para isso inclua o código abaixo no evento Click do botão:

 Protected Sub btnDownload_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDownload.Click
        Dim arquivo As FileInfo
        Dim nomeArquivo As String

        'obtem o nome completo do arquivo seleiconado
        nomeArquivo = Server.MapPath("Images") & "\" & lstArquivos.SelectedItem.Text

        'obtem os dados do arquivo
        arquivo = New FileInfo(nomeArquivo)
        'gera o stream no navegador
        Response.Clear()
        Response.AddHeader("Content-Disposition", "attachment; filename=" & lstArquivos.SelectedItem.Text)
        Response.AddHeader("Content-Length", arquivo.Length.ToString())
        Response.ContentType = "application/octet-stream"
        Response.WriteFile(nomeArquivo)
        Response.End()

    End Sub

Este código obtem o nome do arquivo selecionado , obtém os dados do arquivo e inicia o download.

Executando o projeto do iremos obter:

Página de Login
Página de Download

Selecionando o arquivo vemos a janela Abrir com opção para salvar o arquivo ou exibi-lo.

Dica: Estamos trabalhando com arquivos que já existem mas se você precisar trabalhar com uma imagem gerada na memória você pode usar

Response.BinaryWrite() para gerar um stream de array de bytes ou escrever a saída diretamente em Response.OutputStream.

Exemplo:
Bitmap bmp = gerando imagem bmp
Response.ContentType = "image/jpeg"
Response.AppendHeader("Content-Disposition","attachment; filename=LeftCorner.jpg")
bmp.Save(Response.OutputStream, ImageFormat.Jpeg)

Nota: Se você quiser disponibilizar um arquivo para download diretamente em um hiperlink em uma páginas ASP.NET pode fazer assim:

1- Defina o hiperlink na página conforme abaixo:

<a href="download.aspx?arquivo=/Imagens/teste.gif">Download da imagem</a>

2- Defina o arquivo download.aspx para receber como parâmetro (via QueryString) o nome do arquivo:

<%@ Page language="vb" runat="server" explicit="true" strict="true" %>
<script language="vb" runat="server">
Sub Page_Load(Sender As Object, E As EventArgs)
	Dim strRequest As String = Request.QueryString("arquivo")
          'obtem o caminho do arquivo    
	If strRequest <> "" Then 
		Dim path As String = Server.MapPath(strRequest)
		Dim arquivo As System.IO.FileInfo = New System.IO.FileInfo(path) '
                    'verifica se o arquivo existe no servidor
		If file.Exists Then
			Response.Clear()
			Response.AddHeader("Content-Disposition", "attachment; filename=" & arquivo.Name)
			Response.AddHeader("Content-Length", file.Length.ToString())
			Response.ContentType = "application/octet-stream"
			Response.WriteFile(file.FullName)
			Response.End 'if file does not exist
		Else
			Response.Write("Este arquivo não existe.")
		End If 
	Else
		Response.Write("Forneça o nome do arquivo para download.")
	End If
End Sub
</script>

Em outro artigo abordarei o problema de forçar o download de um arquivo. Aguarde...

Pegue o projeto completo aqui: acessoSeguroComDownload.zip

Eu sei é apenas ASP .NET, simples, simples assim ...

Referências:

José Carlos Macoratti