Back-End

14 mai, 2009

Manipulação de dados BLOB com PHP e MySQL

Publicidade

Sem dúvida
alguma, uma das perguntas mais frequentes em relação ao MySQL é: “como
posso armazenar arquivos em uma base de dados?”. A resposta é: tens que
usar o tipo de dados BLOB. Estes BLOBs (Binary Large Objects) podem
armazenar praticamente qualquer tipo de dados, incluindo documentos do
MS Word, imagens gif/jpeg, arquivos PDF, mp3, etc.

Neste
artigo vamos ver como criar um repositório de arquivos binários usando
PHP e MySQL para poder armazenar diferentes tipos de arquivos. Veremos
como armazenar cada um dos arquivos em uma base de dados, para
posteriormente recuperá-los.

Para testar os exemplos deste
artigo, é necessário ter acesso a um servidor com suporte a PHP, além
de contar com um servidor MySQL. Assumindo que você conte com os privilégios apropriados para criar a base dados, e que o MySQL está
rodando no mesmo servidor que o PHP, vamos iniciar o desenvolvimento.

Criando a base de dados

Nosso repositório de documentos usará uma base dados que contenha unicamente uma tabela para armazenar todos os documentos. O banco de dados será chamado de “repositorio“, e a tabela de “arquivos“.

Código SQL para criar a tabela

CREATE TABLE arquivos( 
id int not null auto_increment primary key,
nome varchar(50),
titulo varchar(50),
conteudo mediumblob,
tipo varchar(50));

Agora temos uma base chamada repositorio, que contém uma tabela chamada arquivos.

Veja abaixo informações sobre cada campo da tabela arquivos:

  • id – um
    número inteiro que nos proporcionará um identificador único para cada
    arquivo que iremos armazenar. Este será incrementado automaticamente
    cada vez que for inserido um novo registro.
  • nome – o nome original do arquivo, por exemplo, fot.gif, curriculum.doc, etc.
  • titulo –
    uma breve descrição de cada arquivo que será gravada na tabela, por
    exemplo “Carta para minha noiva”, ou “A foto do meu irmão”. Este título
    será usado posteriormente na visualização dos arquivos do repositório
    em uma página web.
  • conteudo – um campo do tipo
    binário (blob) para guardar o conteúdo de cada arquivo. Na nossa tabela
    usamos um tipo mediumblob, o qual pode armazenar arquivos de até 16Mb.
  • ipo – como veremos mais adiante, cada arquivo (seja um .doc, .gif, .pdf, etc) tem um tipo único. Quando se envia um
    arquivo
    para o servidor web através de uma página web, o navegar envia ao
    servidor a informação acerca do tipo de arquivo, o tipo de conteúdo do
    arquivo, etc. Os tipos de conteúdo são simples cadeias. O tipo de
    conteúdo para um arquivo MS WORD é “application/msword”, o tipo de
    conteúdo para uma imagem é “image/gif”, etc.

Agregando arquivos à base de dados

Agora
que temos a base de dados do nosso repositório e sabemos a finalidade
de cada campo, vamos criar uma simples página web que permita
selecionar um arquivo desde o navegador para posteriormente enviá-lo
para um script em PHP que ficará encarregado de armazená-lo em nossa
base de dados.A página web será nomeada escolher_arquivo.html e o script em PHP será chamado de guardar_arquivo.php.

A
página web pode conter todo o código HTML que se deseje, mas é
necessário que se inclua o seguinte formulário para que se tenha a
opção de escolher um arquivo e enviá-lo ao servidor.

<!-- ...código anterior -->
<form enctype="multipart/form-data" action="guardar_arquivo.php" method="post">
Descrição <input type="text" name="titulo" size="30">
Arquivo <input type="file" name="arquivo">
<input type="submit" value="Enviar arquivo">
</form>
<!-- ...código posterior -->

Do código que escrevemos temos que frisar o seguinte:

  • o formulário necessita de um atributo enctype com um valor multipart/form-data
  • o método de envio tem que ser POST
  • tem que ser usado pelo menos um campo do tipo FILE

Estes são os três requerimentos básicos que a página HTML deve cumprir para que seja possível enviar o arquivo para o servidor.

Antes
de escrever o código do script guarda_arquivo.php, vamos comentar algo
acerca da forma como serão recebidos os dados do arquivo em questão.

Desde a versão 4.1 do PHP é recomendada a utilização da variável $_FILES
para a leitura dos dados do arquivo que está sendo enviado ao servidor.
Abaixo estão listadas os índices e parâmetros recebidos pela variável.
Note que o nome dos índices depende de como é nomeado o campo do tipo
FILE no formulário.

$_FILES[‘arquivo’][‘name’]

Nome original do arquivo
$_FILES[‘arquivo’][‘type’]

O tipo MIME do arquivo, … image/gif, application/pdf, application/msword,.. etc
$_FILES[‘arquivo’][‘size’]
O tamanho do arquivo em bytes
$_FILES[‘arquivo’][‘tmp_name’]

O local do arquivo temporário que se cria quando o arquivo é enviado ao
servidor. É nesta variável que são lidos todos os dados do arquivo em
si. Se estes dados não são copiados ou movidos para outro lugar, ou em
nosso caso, armazenados em uma base de dados, podem ser perdidos, já
que o PHP elimina esses arquivos depois de um determinado tempo.

Por exemplo, estes são os possíveis valores para um arquivo j-odbc.zip que foi enviado ao servidor:

$_FILES["arquivo"][name] => j-jdbc.zip
$_FILES["arquivo"][type] => application/zip
$_FILES["arquivo"][tmp_name] => /tmp/phpvXQpqP
$_FILES["arquivo"][size] => 337945

Vale
ressaltar que devem ser revistos e, se necessário modificar as
seguintes variáveis no arquivo de configuração do PHP para que você
possa fazer o upload dos arquivos para o servidor, e pode ser gerida
por um script PHP.

  • file_uploads – diz ao PHP se pode ou não ser feito o envio de arquivos para o servidor. Essa variável deve ter o valor  “On”.
  • upload_max_filesize
    – diz ao PHP qual o tamanho máximo do arquivo que pode ser enviado ao
    servidor. Pode ser utilizado o sufixo “M” para indicar o valor em
    Megabytes, por exemplo, com um valor 2M se aceita um arquivo máximo de
    2 Megabytes.
  • upload_tmp_dir – é o diretório para onde será copiado temporariamente o conteúdo do arquivo quando for enviado ao
    servidor.

Agora é o momento de mostrar o código PHP que vai armazenar o arquivo em nossa base de dados.

/* guardar_arquivo.php */

require("dbconnect.inc.php");

$arquiivo = $_FILES["arquivo"]["tmp_name"];
$tamanho = $_FILES["arquivo"]["size"];
$tipo    = $_FILES["arquivo"]["type"];
$nome  = $_FILES["arquivo"]["name"];
$titulo  = $_POST["titulo"];

if ( $arquivo != "none" )
{
$fp = fopen($arquivo, "rb");
$conteudo = fread($fp, $tamanho);
$conteudo = addslashes($conteudo);
fclose($fp);

$qry = "INSERT INTO arquivos VALUES
(0,'$nome','$titulo','$conteudo','$tipo')";

mysql_query($qry);

if(mysql_affected_rows($conn) > 0)
print "O arquivo foi gravado na base de dados.";
else
print "Não foi possível gravar o arquivo na base de dados.";
}
else
print "Não foi possível carregar o arquivo para o servidor.";

O arquivo dbconnetc.inc.php contém unicamente as instruções para conexão ao MySQL e selecionar a base de dados que será utilizada.

/* dbconnect.inc.php */

$conn = mysql_connect("localhost","usuário","senha");
mysql_select_db("repositorio");

Listando os arquivos da base de dados


que gravamos alguns arquivos no nosso repositório, agora podemos listar
as informações deles, para posteriomente fazermos o download. 

/* listar_arquivos.php */

require("dbconnect.inc.php");

$qry = "SELECT id, nome, titulo, tipo FROM arquivos";
$res = mysql_query($qry);

while($fila = mysql_fetch_array($res))
{
print "$fila[titulo]
<br>
$fila[nome] ($fila[tipo])
<br>
<a href='baixar_arquivo.php?id=$fila[id]'>Fazer Download</a>
<br>
<br>";
}

Fazendo o download dos arquivos da base de dados

Como se pode observar no código anterior, foi colocado um link para cada arquivo, chamado baixar_arquivo.php. A funcionalidade deste script será ler os dados dos arquivos que estão gravados na base de dados e enviá-los ao navegador. 

Dependendo do tipo de arquivo da qual se trate, o navegador poderá mostrá-lo por ele mesmo o conteúdo do arquivo.

/* Script baixar_arquivo.php */

require("dbconnect.inc.php");

$qry = "SELECT tipo, conteudo FROM arquivos WHERE id=$id";
$res = mysql_query($qry);
$tipo = mysql_result($res, 0, "tipo");
$conteudo = mysql_result($res, 0, "conteudo");

header("Content-type: $tipo");
print $conteudo;

Comentário Finais

Como
se pode observar, o código PHP dos scripts é bem simples, e não tem
nenhum grau de dificuldade. O código foi desenvolvido com o propósito
mais simples possível, para que possa ser melhorado e utilizado em
aplicações mais robustas.