Olá amigos! Neste artigo vou mostrar como criar arquivos .ZIP e como descompactar utilizando o ASP.net.
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