.NET

23 jan, 2008

Crie Arquivos .ZIP com ASP.NET

Publicidade

Olá amigos! Neste artigo vou mostrar como criar arquivos .ZIP e como descompactar utilizando o ASP.net.

Imagem de exemplo do exemplo deste artigo.Imagem de exemplo do exemplo deste artigo.

Um pouco de conhecimento antes de programarmos

Arquivos .zip é um formato muito conhecido. Em Matemática, um dos modos de se obter uma compressão de arquivos, é através de Transformada de Fourier. A compressão e compactação são importantíssimas para conseguirmos informações em tempos menores de transmissão, de forma mais barata possível.

Qual a diferença entre Compressão e Compactação?

A principal diferença entre os dois termos é que compactação não há perda de informação, enquanto que na compressão há perda. O Formato .MP3 é um exemplo de Compressão, pois há perda de informação, embora nossos ouvidos não notem muito. Mesmo entre os Mp3, temos aqueles com maior qualidade (menos perda) e os de menores qualidades (maior perda).

Entre os métodos mais conhecidos de compactação estão:

  • Codificação por carreira
  • Codificação por Shannon-Fano
  • Codificação de Huffman (muito utilizado para compactar texto)
  • Codificação de Lempel-Ziv-Welch (LZW)
  • Codificação aritmética

Entre os métodos mais conhecidos de compressão estão:

  • Redução do domínio
  • Redução do espaço de quantização
  • Codificação preditiva
  • Codificação por sub-bandas
  • Codificação por transformadas
  • Quantização vetorial

Pré-requisitos

Este artigo foi montado nas configurações abaixo. Não foi testado em outros ambientes.

  • Framework ASP.NET 2.0 com VB.net
  • Visual Studio 2005.

Mãos a obra

Clique aqui para dar download no projeto de exemplo.

Primeiro, crie uma solução no seu VisualStudio. Adicione um novo projeto Web, e referencie a Biblioteca SharpZLib.

Caso você esteja usa utilizando a versão Express, crie um novo website, e coloque ICSharpCode.SharpZipLib.dll na pasta /bin.

Em seguida, vamos criar uma página chamada zip.ASPX.

Compactando Diretório Inteiro

Para compactar o diretório, você terá que informar o diretório de origem e o arquivo de destino.


''' <summary>
    ''' Evento do botão, gerar diretório
    ''' </summary>
    Protected Sub btnGerar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGerar.Click
        gerarZipDiretorio(txtOrigem.Text, txtDestino.Text)
        subInitDescompactarArquivos()
    End Sub

    ''' <summary>
    ''' Este método gera um zip, a partir de um diretório
    ''' </summary>
    ''' <param name="sDiretorioOrigem">
    ''' Diretório que será zipado
    ''' </param>
    ''' <param name="sDiretorioDestino">
    ''' Diretório que receberá o arquivo zipado
    ''' </param>
    ''' <remarks>
    ''' </remarks>
    Public Sub gerarZipDiretorio(ByVal sDiretorioOrigem As String, ByVal sDiretorioDestino As String)

        Dim sz As New FastZip()
        Dim sArquivoZip As String = String.Empty

        ' Aqui vou criar um nome do arquivo, com 6 caracteres randômicos.
        ' O Guid é um método do .net que gera string aleatórias únicas, baseada na hora e no
        ' endereço MAC na máquina gerada.
        sArquivoZip = "MeuZip" & Left(Guid.NewGuid.ToString, 6) & ".zip"

        ' Só um tratamento para garantir mais estabilidade
        If Right(sDiretorioOrigem, 1) <> "\" Then
            sDiretorioOrigem = sDiretorioOrigem & "\"
        End If

        ' Só um tratamento para garantir mais estabilidade
        If Right(sDiretorioDestino, 1) <> "\" Then
            sDiretorioDestino = sDiretorioDestino & "\"
        End If

        If Not Directory.Exists(sDiretorioDestino) Then
            lblErro.Text = "O Diretório de Destino informado não existe: <br />" & sDiretorioDestino
            Exit Sub
        End If

        If Not Directory.Exists(sDiretorioOrigem) Then
            lblErro.Text = "O Diretório de Origem informado não existe: <br />" & sDiretorioOrigem
            Exit Sub
        End If

        sz.CreateZip(sDiretorioDestino & sArquivoZip, sDiretorioOrigem & "" & "\", True, "", "")

        ' Aqui eu habilito o download do arquivo.
        ' Muito útil se você quiser salvar em diretórios protegidos
        ' Ou não acessível pela raíz do seu projeto web.
        HttpContext.Current.Response.TransmitFile(sDiretorioDestino & sArquivoZip)

        ' "Limpo" o objeto
        sz = Nothing

    End Sub

Obs.:

Você pode definir uma senha para seu .zip, utilizando a propriedade “password”.

Compactando Somente um Arquivo

Para compactar somente um arquivo, você terá que informar o arquivo a ser compactado, e o diretório de destino.


    ''' <summary>
    ''' Evento do botão gerar Arquivo
    ''' </summary>
    Protected Sub btnGerarArquivo_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnGerarArquivo.Click
        gerarZipArquivo(txtArquivoOrigem.Text, txtArquivoDestino.Text)
        subInitDescompactarArquivos()
    End Sub

    ''' <summary>
    ''' Este método gera um zip, a partir de um diretório
    ''' </summary>
    ''' <param name="sArquivoOrigem">
    ''' Arquivo que será zipado
    ''' </param>
    ''' <param name="sDiretorioDestino">
    ''' Diretório que receberá o arquivo zipado
    ''' </param>
    ''' <remarks>
    ''' </remarks>
    Public Sub gerarZipArquivo(ByVal sArquivoOrigem As String, ByVal sDiretorioDestino As String)

        Dim sz As New FastZip()
        Dim sArquivoZip As String = String.Empty

        ' Aqui vou criar um nome do arquivo, com 6 caracteres randômicos.
        ' O Guid é um método do .net que gera string aleatórias únicas, baseada na hora e no
        ' endereço MAC na máquina gerada.
        sArquivoZip = "MeuZip" & Left(Guid.NewGuid.ToString, 6) & ".zip"

        ' Só um tratamento para garantir mais estabilidade
        If Right(sDiretorioDestino, 1) <> "\" Then
            sDiretorioDestino = sDiretorioDestino & "\"
        End If

        If Not Directory.Exists(sDiretorioDestino) Then
            lblErroArquivo.Text = "O Diretório de Destino informado não existe: <br />" & sDiretorioDestino
            Exit Sub
        End If

        If Not File.Exists(sArquivoOrigem) Then
            lblErroArquivo.Text = "O Arquivo de Origem informado não existe: <br />" & sArquivoOrigem
            Exit Sub
        End If

        ' Crio um arquivo do tipo stream, aprontando para o meu zip de destino.
        Dim strmZipOutputStream As ZipOutputStream
        strmZipOutputStream = New ZipOutputStream(File.Create(sDiretorioDestino & sArquivoZip))

        ' Seto o nível de compressão (0->Sem compressão / 9-> Compressão Máxima)
        strmZipOutputStream.SetLevel(9)

        ' Leio o arquivo de origem
        Dim strmFile As FileStream = File.OpenRead(sArquivoOrigem)
        Dim abyBuffer(strmFile.Length - 1) As Byte

        strmFile.Read(abyBuffer, 0, abyBuffer.Length)

        ' Aqui eu trato para pegar somente o arquivo, sem os diretórios
        ' O split é um método que separa a string, de acordo com um caractere, no meu caso "\"
        ' Cada indice da minha matriz é um diretório, e o ultimo é o arquivo
        Dim sAuxArquivo As String() = Split(sArquivoOrigem, "\")

        ' Crio uma variável, adicionando o meu Arquivo ao Zip
        ' Com ubound, eu pego o ultimo índice da minha matriz, que é o nome do meu arquivo.
        Dim objZipEntry As ZipEntry = New ZipEntry(sAuxArquivo(UBound(sAuxArquivo)))

        ' Seto a data de criação
        objZipEntry.DateTime = DateTime.Now

        ' Informo o tamanho do stream. (Do meu arquivo a ser zipado)
        objZipEntry.Size = strmFile.Length

        ' Fecho meu stream para liberar memória
        strmFile.Close()

        ' Adiciono no objeto para gerar o zip.
        strmZipOutputStream.PutNextEntry(objZipEntry)
        strmZipOutputStream.Write(abyBuffer, 0, abyBuffer.Length)

        ' "Limpo" o objeto
        strmZipOutputStream.Finish()
        strmZipOutputStream.Close()

        ' Aqui eu habilito o download do arquivo.
        ' Muito útil se você quiser salvar em diretórios protegidos
        ' Ou não acessível pela raíz do seu projeto web.
        HttpContext.Current.Response.TransmitFile(sDiretorioDestino & sArquivoZip)

    End Sub

Descompactando um arquivo .zip

Para descompactar um arquivo .zip você terá que informar o arquivo, e o diretório de destino.



    Protected Sub btnDescompactar_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnDescompactar.Click
        descompactarZip(txtArquivoParaDescompactar.Text, txtDescompactarArquivos.Text)
    End Sub

    ''' <summary>
    ''' Sub que descompacta um arquivo .zip apra um diretório
    ''' </summary>
    ''' <param name="sArquivoZip">
    ''' Arquivo para ser descompactado
    ''' </param>
    ''' <param name="sDiretorioParaDescompactar">
    ''' Diretório para ser descompactado
    ''' </param>
    ''' <remarks></remarks>
    Private Sub descompactarZip(ByVal sArquivoZip As String, ByVal sDiretorioParaDescompactar As String)

        Dim oMeuZip As New FastZip

        ' Se o arquivo não existe eu aviso o usuário
        If Not File.Exists(sArquivoZip) Then
            lblErroDescompactar.Text = ("Arquivo zip não existe: " & sArquivoZip)
            Exit Sub
        End If

        ' Se o arquivo não for zip, eu aviso o usuário
        If LCase(Right(sArquivoZip, 3)) <> "zip" Then
            lblErroDescompactar.Text = ("Arquivo não é do formato .zip: " & sArquivoZip)
            Exit Sub
        End If

        ' Se o arquivo não for zip, eu aviso o usuário
        If Not Directory.Exists(sDiretorioParaDescompactar) Then
            lblErroDescompactar.Text = ("Diretório para descompactar os arquivos não existe: " & sDiretorioParaDescompactar)
            Exit Sub
        End If

        ' "Deszipo" o arquivo, sem nunca sobrescrever
        oMeuZip.ExtractZip(sArquivoZip, sDiretorioParaDescompactar, FastZip.Overwrite.Never)

        lblErroDescompactar.Text = "Arquivo Descompactado com sucesso!!!!!"
    End Sub

Para você testar!

Para que você possa testar, colocamos um formulário, e um código de inicialização da página.

Formulário:


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Criar Arquivos Zip em Asp.Net</title>
    <style type="text/css">
    body, input{
    font-family: verdana;
    font-size: 10px;
    }
    
    </style>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <strong>Este exemplo utiliza componentes de terceiros. Verifique o termo de uso.
                .</strong>
            <br />
            <br />
            <fieldset>
                <legend>Criar Arquivo Zip do Diretório Inteiro </legend> 
                <table style="border: none;">
                    <tr>
                        <td>
                            Diretório de Origem:
                        </td>
                        <td>
                            <asp:TextBox ID="txtOrigem" runat="server" Columns="60"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            Diretório de Destino:
                        </td>
                        <td>
                            <asp:TextBox ID="txtDestino" runat="server" Columns="60"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <asp:Button runat="server" ID="btnGerar" Text="Gerar Zip do Diretório inteiro" />
                            <asp:Label runat="server" ID="lblErro" Font-Bold="true" ForeColor="red"></asp:Label>
                        </td>
                    </tr>
                </table>
            </fieldset>
            <br />   <br />
            <fieldset>
                <legend>Criar Arquivo Zip de um único Arquivo </legend> 
                <table style="border: none;">
                    <tr>
                        <td>
                            Arquivo para ser "zipado":
                        </td>
                        <td>
                            <asp:TextBox ID="txtArquivoOrigem" runat="server" Columns="60"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            Diretório de Destino:
                        </td>
                        <td>
                            <asp:TextBox ID="txtArquivoDestino" runat="server" Columns="60"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2">
                            <asp:Button runat="server" ID="btnGerarArquivo" Text="Gerar Zip de um único Arquivo" />
                            <asp:Label runat="server" ID="lblErroArquivo" Font-Bold="true" ForeColor="red"></asp:Label>
                        </td>
                    </tr>
                </table>
            </fieldset>
        </div>
        <br />   <br />
        <fieldset>
            <legend>Descompactar Arquivo .ZIP </legend> 
            <table style="border: none;">
                <tr>
                    <td>
                        Arquivo para ser "deszipado":
                    </td>
                    <td>
                        <asp:TextBox ID="txtArquivoParaDescompactar" runat="server" Columns="60"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td>
                        Diretório para arquivos serem descompactados :
                    </td>
                    <td>
                        <asp:TextBox ID="txtDescompactarArquivos" runat="server" Columns="60"></asp:TextBox>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <asp:Button runat="server" ID="btnDescompactar" Text="Descompactar arquivo zip" />
                        <asp:Label ID="lblErroDescompactar" runat="server" Font-Bold="true" ForeColor="red"></asp:Label>
                    </td>
                </tr>
            </table>
        </fieldset>
    </form>
</body>
</html>

Inicialização da Página


    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        If Not Page.IsPostBack Then
            ' Aqui eu dou um valor inicial, só para te ajudar a começar com um teste
            txtDestino.Text = Server.MapPath("") & "\Destino\"
            txtOrigem.Text = Server.MapPath("") & "\Origem\"

            ' Arquivo
            txtArquivoDestino.Text = Server.MapPath("") & "\Destino\"
            txtArquivoOrigem.Text = Server.MapPath("") & "\Origem\Figura.jpg"

            ' Descompactar
            txtDescompactarArquivos.Text = Server.MapPath("") & "\Descompactar\"
            subInitDescompactarArquivos()
        End If

    End Sub

    ''' <summary>
    ''' Sub só para demonstação, para você poder dezipar um arquivo, depois de enviá-lo
    ''' </summary>
    ''' <remarks></remarks>
    Protected Sub subInitDescompactarArquivos()
        Dim sArquivos As String()
        Dim sArquivo As String

        ' Seleciono todos os arquivos do tipo zip.
        sArquivos = Directory.GetFiles(txtArquivoDestino.Text, "*.zip")

        For Each sArquivo In sArquivos
            txtArquivoParaDescompactar.Text = sArquivo
            Exit For
        Next

    End Sub

Considerações finais

É possível também trabalhar com arquivos .tar, Gzip e BZip2 de forma análoga.

Espero que tenha gostado!

Clique aqui para dar download no projeto de exemplo.

Forte Abraço