1 Apresentao
Dessa forma, este tutorial tem por objetivo mostrar um exemplo simples de gerenciamento de imagens
em uma aplicao web utilizando apenas recursos do J2EE Core.
O exemplo foi construdo no Glassfish Server com JEE 7 atravs do IDE Netbeans 8.1. Os testes
envolvendo armazenamento em banco de dados foram testados no MySQL 5.7.1.
Os recursos utilizados para upload e download de arquivos foram baseados nos seguintes tutoriais dis-
ponveis na web: https://docs.oracle.com/javaee/7/tutorial/servlets016.htm e http://www.codejava.net/java-
ee/servlet/java-servlet-download-file-example, respectivamente.
No contexto atual da web, grande parte dos recursos disponveis em uma pgina podem ser exclusivos
para usurios cadastrados e autenticados. Assim, comearemos o exemplo criando uma estrutura
simples para que o usurio possa logar na pgina e ter acesso aos recursos disponveis.
Inicialmente, crie uma arquivo index.jsp no projeto, incluindo no corpo da pgina o cdigo HTML
mostrado abaixo. O resto do cdigo HTML pode ser mantido como criado pelo Netbeans.
Cdigo 1: index.jsp
1 < form a c t i o n = " l o g a r " method = " p o s t " >
2 <p>
3 < l a b e l f o r =" l o g i n ">Login : < / l a b e l >
4 < i n p u t t y p e = " p a s s w o r d " name= " l o g i n " i d = " l o g i n " >
5 < / p>
6 <p>
7 < l a b e l f o r = " s e n h a " > Senha : < / l a b e l >
8 < i n p u t t y p e = " p a s s w o r d " name= " s e n h a " i d = " s e n h a " >
9 < / p>
10 <p>
11 < i n p u t type =" submit " value =" E n t r a r ">
1
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
12 < / p>
13 < / form >
Este cdigo apenas criar um formulrio como mostrado na figura 1. O prximo passo criar o servlet
Logar para o qual sero enviados os dados do formulrio web. Esse servlet deve apenas receber os
dados do usurio e realizar o login na pgina caso as informaes de usurio estejam corretas. Para
simplificar o exemplo e no distanciar do foco do tutorial, ser considerado que o sistema possui
apenas um usurio com o login "admin" e a senha "1234" e a validao ser feita utilizando uma
estrutura de seleo do tipo if . . . else. Ser utilizado um atributo "usuario" na sesso que guardar
o login do usurio logado para definir se existe algum logado na pgina. Quando ningum estiver
logado, essa posio ser definida como null.
Para organizar o projeto, crie no Netbeans os pacotes: modelo, controle e persistencia. Estes pacotes
sero utilizados no decorrer do desenvolvimento do projeto.
No pacote controle crie o servlet Logar. No momento de criar o Serlvet no esquea de mudar o
parmetro "Padro(es) de url "para "/logar"com "l minsculo ". Caso contrrio, a submisso do
formulrio no encontrar a pgina de destino. Se tiver ocorrido tudo certo, no incio do servlet
aparecer a seguinte anotao:
Cdigo 2: Logar.java
1 @WebServlet ( name = " L o g a r " , u r l P a t t e r n s = { " / l o g a r " } )
Neste servlet, e na maioria dos exemplos, ser alterado apenas o contedo do try que est no mtodo
processRequest. Este cdigo tem o seguinte objetivo: ler os campos de login e senha e gravar o usurio
na sesso e redirecionar para a pgina inicial. O contedo do mtodo ficar da seguinte forma:
Cdigo 3: Logar.java
1 p r o t e c t e d void processRequest ( HttpServletRequest request , HttpServletResponse
response ) throws ServletException , IOException {
2 r e s p o n s e . s e t C o n t e n t T y p e ( " t e x t / h t m l ; c h a r s e t =UTF8" ) ;
3 t r y ( P r i n t W r i t e r out = response . getWriter ( ) ) {
4 / / L e i t u r a dos dados e n v i a d o s
5 String login = request . getParameter ( " login " ) ;
6 S t r i n g senha = r e q u e s t . getParameter ( " senha " ) ;
7 / / R e c u p e r a o b j e t o que g e r e n c i a a s e s s a o
8 HttpSession session = request . getSession () ;
9 / / V e r i f i c a se usurio e senha e s t a o c o r r e t o s
10 i f ( " admin " . e q u a l s ( l o g i n ) && " 1234 " . e q u a l s ( s e n h a ) ) {
11 s e s s i o n . s e t A t t r i b u t e ( " u s u a r i o " , " admin " ) ;
12 } else {
13 / / Grava mensagem de e r r o
2
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Uma vez que esteja funcionando o servlet Logar, necessrio fazer com que a pgina index.jsp
reconhea o usurio que est logado. Para isto, faremos as seguintes alteraes:
Para melhorar a organizao da pgina e legibilidade, crie no diretrio web uma pasta com o nome au-
xiliares onde sero criados arquivos com os cdigos do formulrio de login, do menu e do formulrio
de imagem.
Cdigo 5: menu.jsp
1 <p>
2 <a h r e f = " i n d e x . j s p ? p=1 " >
3 G e r e n c i a r Imagens
4 < / a> |
5 <a h r e f = " s a i r " > S a i r < / a >
6 < / p>
3
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Feito isso, basta adicionar o input responsvel pela submisso de arquivo que o input type="file".
Ele possui um atributo accept que determina que tipo de arquivo pode ser aceito e possui a seguinte
sintaxe:
1 < i n p u t t y p e = " f i l e " a c c e p t = " f i l e _ e x t e n s i o n | a u d i o / | v i d e o / | image / | m e d i a _ t y p e " >
Mais informaes sobre o input type="file" podem ser encontradas em: w3schools.
Cdigo 6: formImagem.jsp
1 <body >
2 < form a c t i o n = " u p l o a d " method = " p o s t " e n c t y p e = " m u l t i p a r t / formd a t a " >
3 <p>
4 < l a b e l f o r =" d e s c r i c a o "> Descricao : < / l a b e l >
5 < i n p u t t y p e = " t e x t " name= " d e s c r i c a o " i d = " d e s c r i c a o " >
6 < / p>
7 <p>
8 < l a b e l f o r =" a r q u i v o ">Arquivo : < / l a b e l >
9 < i n p u t t y p e = " f i l e " name= " a r q u i v o " i d = " a r q u i v o " a c c e p t = " image / " >
10 < / p>
11 <p>
12 < i n p u t type =" submit " value =" Enviar ">
13 < / p>
14 < / form >
15 < / body >
Aps criadas as pginas auxiliares, necessrio refazer o arquivo index.jsp para que eles sejam inclu-
dos a depender do estado do login do usurio (logado ou no). Para fazer essas incluses utilizando
condicionais foi utilizada a tag if do Java Standard Tag Library JSTL.
Resumidamente, as tag if avaliar o cdigo do atributo text e caso verdadeira executar o cdigo
dentro da tag. As variveis utilizadas no teste sero buscadas por padro na sesso de navegao.
Mais informaes sobre o funcionamento do JSTL podem ser encontrada em tutorials point e safari
books online.
Neste momento, j deve ser possvel visualizar a pgina como mostrado na imagem 2.
Antes de fazer o servlet Upload que realizar o upload de imagens, vamos fazer o servlet Sair para
que seja possvel sair da pgina.
Basta criar no pacote de controle um servlet que ter o seguinte cdigo no mtodo processRequest:
4
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Cdigo 8: Sair.java
1 p r o t e c t e d void processRequest ( HttpServletRequest request , HttpServletResponse
response )
2 throws ServletException , IOException {
3 r e s p o n s e . s e t C o n t e n t T y p e ( " t e x t / h t m l ; c h a r s e t =UTF8" ) ;
4 t r y ( P r i n t W r i t e r out = response . getWriter ( ) ) {
5 HttpSession session = request . getSession () ;
6 / / d e s t r o y o s o b j e t o s da s e s s a o
7 session . invalidate () ;
8 / / volta para o i n i c i o
9 response . sendRedirect ( " index . jsp " ) ;
10 }
11 }
Esse servlet Sair apenas excluir os dados da sesso de navegao e redirecionar o usurio de volta
para a pgina inicial.
Gerenciar imagem, ou outros tipos de arquivos, em aplicaes web podem ir alm de gravar e ex-
cluir essas pginas em diretrios. Usualmente necessrio definir que usurios ou grupos de usurios
podem ter acesso ao arquivo, pode ser til ter informaes acerca de cada arquivo para agilizar inde-
xao e busca e todos estes recursos podem ser melhor gerenciados em uma classe, sob a perspectiva
da orientao a objetos.
A maioria dos SGBD possuem recursos para gravar contedos binrios, como campos do tipo BLOB
no MySQL. No entanto, visando agilizar a busca de informaes no banco e a manipulao dos
arquivos fora do SGBD para backups e aes similares, neste exemplo, trabalharemos com uma classe
Imagem que entre seus atributos possui um atributo endereco que armazena o caminho da imagem
no sistemas de arquivos do servidor. Assim apenas os metadados e o endereo da imagem sero
armazenados no banco.
5
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
3 p r i v a t e String endereco ;
4 private String descricao ;
5
6 p u b l i c Imagem ( l o n g i d , S t r i n g e n d e r e c o , S t r i n g d e c r i c a o ) {}
7
8 p u b l i c Imagem ( S t r i n g e n d e r e c o , S t r i n g d e c r i c a o ) {}
9
10 p u b l i c l o n g g e t I d ( ) {}
11
12 p u b l i c v o i d s e t I d ( l o n g i d ) {}
13
14 p u b l i c S t r i n g g e t E n d e r e c o ( ) {}
15
16 p u b l i c v o i d s e t E n d e r e c o ( S t r i n g e n d e r e c o ) {}
17
18 p u b l i c S t r i n g g e t D e s c r i c a o ( ) {}
19
20 p u b l i c v o i d s e t D e s c r i c a o ( S t r i n g d e s c r i c a o ) {}
21
22 }
Uma vez que os detalhes de conexo com bancos de dados fogem ao escopo deste tutorial, os detalhes
das classes podero ser encontrados nos exemplos disponibilizados juntos com o tutorial.
Neste exemplo a conexo com o banco de dados foi implementada utilizando o JDBC atravs do
driver MySQL JDBC verso 5.1.40, disponvel em site do MySQL. importante adicionar o arquivo
.jar no projeto. No cdigo disponibilizado com o exemplo esse arquivo encontra-se em um diretrio
lib junto com o projeto.
7 p u b l i c s t a t i c Imagem r e c u p e r a r I m a g e m ( l o n g i d ) {}
8
9 p u b l i c s t a t i c C o l l e c t i o n <Imagem> t o d a s I m a g e n s ( ) {}
10 }
Alm das classes, necessrio construir um banco de dados com uma tabela para gerenciar as imagens
disponveis. A tabela imagem foi criada com uma coluna para cada atributo da classe Imagem. Sendo
criada pelo seguinte cdigo:
Cdigo 11: SQL da Tabela Imagem
1 CREATE TABLE imagem (
2 i d INT NOT NULL AUTO_INCREMENT,
3 e n d e r e c o VARCHAR( 4 0 0 ) NOT NULL,
4 d e s c r i c a o VARCHAR( 5 0 0 ) NULL,
6
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
5 PRIMARY KEY ( i d ) )
6 ENGINE = InnoDB ;
Nos testes do exemplo, o banco de dados utilizado foi o banco imagens, com o usurio root, sem
senha. Caso altere os parmetros de conexo com o banco de dados importante alterar o mtodo
getConexao da classe FabricaDeConexoes.
Nos arquivos disponibilizados junto ao tutorial existe o modelo lgico do banco em formato .mwb
(MySQL Workbench) e .sql.
Em qualquer projeto MVC (Model - View - Control), uma vez definidas as camadas de viso e modelo,
o prximo passo conecta-las atravs de classes da camada de controle. Esse ser o papel do servlet
Upload: receber os dados que vm do formulrio de upload de imagem, instanciar objetos das classes
de modelo e persistncia para armazenar as informaes no banco de dados e enviar os arquivos para
um diretrio pr-definido.
Assim como os formulrios que enviam arquivos precisam de uma configurao especfica, os servlets
que os recebem precisam de uma anotao indicando que podem receber dados do tipo multipart. Para
isto, basta adicionar a anotao MultipartConfig do incio da classe:
Cdigo 12: Upload.java
1 @WebServlet ( name = " Upload " , u r l P a t t e r n s = { " / u p l o a d " } )
2 @MultipartConfig
3 p u b l i c c l a s s Upload e x t e n d s H t t p S e r v l e t {
4 ...
5 }
Segue o cdigo do mtodo processRequest do servlet Upload que ser explicado em mais detalhes na
sequncia:
Cdigo 13: Upload.java
1 p r o t e c t e d void processRequest ( HttpServletRequest request , HttpServletResponse
response )
2 throws ServletException , IOException {
3 r e s p o n s e . s e t C o n t e n t T y p e ( " t e x t / h t m l ; c h a r s e t =UTF8" ) ;
4 / / O b j e t o que g r a v a r a o a r q u i v o em um d i r e t o r i o
5 FileOutputStream saida = null ;
6 / / Objeto para l e r arquivo enviado
7 InputStream entrada = null ;
7
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Um dos primeiros passo para compreender este servlet entender como o arquivo enviado atravs do
formulrio chega no servidor. Este arquivo pode ser dividido em vrias partes para ser enviado em
pacotes de rede a depender da configurao da mquina do cliente, do servidor e da rede. Ao chegar
no servidor, este arquivo remontado em um buffer que se comportar de forma similar a um arquivo.
Um objeto da classe Part, retornado pelo mtodo request.getPart que permitir acesso aos dados
deste arquivo. Mais de arquivo pode ser enviado atravs do mesmo formulrio, assim este mtodo
recebe como parmetro uma String contendo o name do campo no formulrio de submisso. Este
objeto da classe Part contm, alm dos bytes do arquivo os dados de seu envio, como o nome do
arquivo, por exemplo.
Atravs deste objeto da classe Part, possvel obter um stream de leitura do arquivo, do tipo InputS-
tream que permitir a leitura dos bytes do arquivo. A partir deste ponto, o procedimento o mesmo
de ler dados em um arquivo binrio em Java desktop e gravar dados binrios em um arquivo.
8
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Os servidores web disponibilizam comumente uma quantidade pequena de memria para cada requi-
sio. Assim, pode ser interessante copiar o arquivo em pequenas partes. Para isso, deve-se usar um
vetor de bytes como buffer de leitura. Neste exemplo foi utilizado um buffer de 1024 bytes.
Uma vez instanciados objetos de leitura e escrita basta utilizar uma estrutura de repetio para copiar
os dados do stream temporrio para um arquivo no sistema de arquivos do servidor. A parte do mtodo
mostrada abaixo faz essa cpia dos dados:
Cdigo 14: Upload.java
1 / / i n s t a n c i a o b j e t o que c o p i a r a o s d a d o s p a r a o u t r o a r q u i v o
2 s a i d a = new F i l e O u t p u t S t r e a m ( e n d e r e c o ) ;
3 / / obtem o b j e t o p a r a l e i t u r a d o s d a d o s e n v i a d o s p e l o f o r m u l a r i o
4 entrada = p a r t f i l e . getInputStream () ;
5 / / s e r a u s a d o como b u f f e r na t r o c a de d a d o s
6 b y t e b y t e s [ ] = new b y t e [ 1 0 2 4 ] ;
7 i n t t = 0 , l e i t u r a =0;
8 / / f a z a c o p i a d o s d a d o s r e s p e i t a n d o o tamanho do b u f f e r
9 w h i l e ( ( t = e n t r a d a . r e a d ( b y t e s ) ) != 1) {
10 l e i t u r a += t ;
11 saida . write ( bytes , 0 , t ) ;
12 }
Um dos passos anteriores cpia do arquivo para um diretrio definir o caminho do arquivo (ende-
reo + nome) no sistema operacional. O nome do arquivo foi gerado a partir de uma combinao da
data/horrio do servidor em milissegundos e o nome do arquivo na mquina do cliente. Essa combi-
nao foi feita para evitar nomes repetidos caso sejam enviados dois arquivos com o mesmo nome.
Observe que o nome do arquivo foi obtido atravs de um funo chamada getFileName. Esta funo
est na classe Upload. Sua implementao sugerida no tutorial disponvel da documentao do JEE.
Observe que os arquivos sero salvos no endereo "c:\web\arquivos\", que deve existir no servidor e
ter permisso de escrita.
Por fim basta instanciar um objeto da classe Imagem e salvar no banco de dados.
Com os passos mostrados at aqui, finalmente deve ser possvel salvar uma imagem. interessante
neste momento enviar uma imagem atravs do formulrio web e garantir que ela chegou no diretrio
especificado e que seus dados forma registrados no banco de dados.
Uma vez que as imagens j podem ser salvas, interessante que o usurio tenha a possibilidade de
excluir e indispensvel que tenha a possibilidade de visualizar. Seguindo a implementao, vamos
9
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
construir mais uma pgina auxiliar que listar as imagens existentes acompanhadas de um link que
permitir sua excluso.
Para isto, devemos utilizar o mtodo todasImagens da classe ImagemDAO. Para obter um cdigo com
boa legibilidade ser utilizada a tag JSTL foreach em combinao com o Java Beans. Em resumo,
ser possvel iterar sobre a coleo de imagens utilizando um conjunto pequeno de tags. Para isso,
precisamos de um mtodo com a assinatura iniciada com get para que possa ser utilizado como um
Bean. Vamos ento adicionar o seguinte mtodo na classe ImagemDAO:
Cdigo 16: ImagemDAO.java
1 p u b l i c C o l l e c t i o n <Imagem> g e t I m a g e n s ( ) {
2 r e t u r n ImagemDAO . t o d a s I m a g e n s ( ) ;
3 }
Este mtodo ser apenas um "atalho"para que o Java Beans possa fazer uma chamada do tipo: new
ImagemDAO().getImagens().
Agora j possvel criar a pgina que listar as imagens. A tag forEach possui dois parmetros, o
items que recebe a coleo que deve percorrer e o var que indica o nome da varivel que ser utilizada
no lao.
A tag useBean vai permitir apenas que um objeto da classe ImagemDAO seja instanciado e armaze-
nado num objeto com o nome dao.
Basta inserir mais uma condio na pgina index.jsp para que a pgina listaImagens.jsp seja includa.
Desta vez alm do usurio estar logado, precisa existir o parmetro p=1 para que as imagens sejam
mostradas. Para que isso funcione, basta incluir mais uma tag if dentro do corpo da pgina index.jsp,
agora aninhada com a tag if usuario != null j existente. O corpo da pgina index.jsp ficar da seguinte
forma:
Cdigo 18: index.jsp
1 <c : i f t e s t = " $ { u s u a r i o == n u l l } " >
2 < j s p : i n c l u d e page=" a u x i l i a r e s / formLogin . j s p " / >
3 </ c : if>
4 <c : i f t e s t = " $ { u s u a r i o ! = n u l l } " >
10
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Ao clicar no link Gerenciar Imagens, as imagens que voc postou j devem ser listadas, como mostra
na figura 3. Vamos comear agora mostrando a construo da opo de excluir.
Observe que o link excluir tem um href do tipo excluir?id=x, onde x o id da imagem. Para que a
excluso funcione, basta o servlet Excluir que apagar a imagem do banco de dados e do diretrio.
Segue o cdigo do mtodo processRequest do servlet Excluir, que faz parte do pacote de controle:
Cdigo 19: Excluir.java
1 p r o t e c t e d void processRequest ( HttpServletRequest request , HttpServletResponse
response )
2 throws ServletException , IOException {
3 r e s p o n s e . s e t C o n t e n t T y p e ( " t e x t / h t m l ; c h a r s e t =UTF8" ) ;
4 t r y ( P r i n t W r i t e r out = response . getWriter ( ) ) {
5 / / recupera sessao
6 HttpSession session = request . getSession () ;
7 / / recupera parametro id
8 i n t id = Integer . parseInt ( request . getParameter ( " id " ) ) ;
9 / / v e r i f i c a s e tem alguem l o g a d o
10 i f ( s e s s i o n . g e t A t t r i b u t e ( " u s u a r i o " ) != n u l l ) {
11 / / r e c u p e r a imagem do b a n c o
12 Imagem img = ImagemDAO . r e c u p e r a r I m a g e m ( i d ) ;
13 F i l e a r q u i v o = new F i l e ( img . g e t E n d e r e c o ( ) ) ;
14 i f ( arquivo . e x i s t s () ) {
15 / / a p a g a a r q u i v o do d i r e t o r i o
16 arquivo . delete () ;
17 }
18 / / a p a g a o b j e t o imagem do b a n c o
19 ImagemDAO . e x c l u i r I m a g e m ( img . g e t I d ( ) ) ;
20 }
21 r e s p o n s e . s e n d R e d i r e c t ( " i n d e x . j s p ? p=1 " ) ;
22 }
23 }
11
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
A opo de excluir imagens j deve estar funcionando, resta somente a opo de exibir imagens. Ob-
serve inicialmente que as imagens no esto no diretrio do projeto e, possivelmente fora do diretrio
web. Assim, no possvel ter no seu site um link direto para estas imagens. Uma caracterstica
importante dessa forma de gerenciar imagens que s estaro disponveis para os usurio autoriza-
dos. Ento a exibio das imagens passar por dois passos: criar um servlet Ver que receber como
parmetro uma imagem e a retornar; exibir a imagem na pgina index.jsp utilizando o servlet Ver.
Pode soar estranho ter um servlet que retornar uma imagem ao invs de um arquivo HTML. Mas
lembre-se que para cada requisio, o servidor web pode ser retornar um arquivo geral ou um arquivo
de hipertexto. Para que o navegador saiba que est recebendo um arquivo para download, devemos
configurar o servlet com alguns parmetros adicionais.
12
Desenvolvimento Web
Tutorial Upload de Arquivos
Diogo Novais
Este servlet tem mais um particularidade. A pgina que o requisitar espera uma imagem, logo
se houver algum erro, faz pouco sentido redirecionar para outra pgina. Assim, o mtodo res-
ponse.sendError est sendo chamado no caso de no haver usurio logado. A contante passada como
parmetro indica o erro de contedo no encontrado (404).
Verificado se tem usurio disponvel, o processo similar ao de upload, mas agora o caminho ser
inverso. Um arquivo do servidor ser copiado no buffer do servidor web.
Para finalizar o exemplo basta apenas exibir a imagem selecionada na pgina inicial. Para isto, vamos
inserir mais uma condicional no arquivo index.jsp, agora verificando o parmetro img que passado
no link da imagem. Caso exista, basta criar uma imagem que ter como fonte (src) o retorno do servlet
Ver que acaba de ser criado. O cdigo do corpo da pgina index.jsp ficar da seguinte forma:
Cdigo 21: index.jsp
1 <c : i f t e s t = " $ { u s u a r i o == n u l l } " >
2 < j s p : i n c l u d e page=" a u x i l i a r e s / formLogin . j s p " / >
3 </ c : if>
4 <c : i f t e s t = " $ { u s u a r i o ! = n u l l } " >
5 < j s p : i n c l u d e p a g e = " a u x i l i a r e s / menu . j s p " / >
6 < j s p : i n c l u d e p a g e = " a u x i l i a r e s / formImagem . j s p " / >
7
8 <c : i f t e s t = " $ { param . p == 1 } " >
9 < j s p : i n c l u d e page=" a u x i l i a r e s / l i s t a I m a g e n s . j s p " / >
10 </ c : if>
11 <c : i f t e s t = " $ { param . img ! = n u l l } " >
12 <img s r c = " v e r ? i d =$ { param . img } " a l t = " Imagem nao e n c o n t r a d a " >
13 </ c : if>
14 </ c : if>
13