Você está na página 1de 13

Desenvolvimento Web

Tutorial Upload de Arquivos


Diogo Novais

Tutorial: Upload de Arquivos com Jsp e Servlets


Este tutorial tem por objetivo mostrar a utilizao de upload e download de arquivos utilizando Servlets em
Java. Para isto, ser construda uma pgina na qual o usurio logado capaz de gerenciar um conjunto de
imagens. assumido no tutorial que o usurio j tem experincia intermediria em Java e j conhece conceitos
bsico de Java Web com Jsp e Servlets. Alm disso, so utilizados recursos de conexo com banco de dados
MySQL com JDBC.

1 Apresentao

Alm de compartilhar hipertextos, uma das grandes possibilidade da Web o compartilhamento de


arquivos. Alguns frameworks, como o Apache Commons disponibilizam um conjunto de ferramentas
para esta tarefa, mas como ocorre tradicionalmente nos frameworks, tem foco em grandes projetos e
escalabilidade, possuindo uma curva de aprendizagem lenta e consumindo muito tempo dos usurios
que querem um primeiro exemplo simples.

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.

2 Iniciando a construo da pgina

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 >

Fig. 1: Formulrio de Login

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

14 S t r i n g msg = " U s u a r i o e / ou s e n h a i n v a l i d o s " ;


15 s e s s i o n . s e t A t t r i b u t e ( " mensagem " , msg ) ;
16 }
17 / / R e d i r e c i o n a de v o l t a p a r a o i n d e x
18 response . sendRedirect ( " index . jsp " ) ;
19 }
20 }

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:

O formulrio de login ser envolvido em um if para s ser mostrado se no tiver ningum


logado;
Ser inserido um menu com as opes de: sair ou gerenciar imagens que ser envolvido em
um if para ser mostrado somente se tiver algum logado;
Por fim, ser incluso um formulrio para cadastro de imagem para ser mostrado somente se
tiver algum logado.

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.

Estes arquivos tero o seguinte cdigo:


Cdigo 4: formLogin.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 = " t e x t " 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 ">
12 < / p>
13 < / form >

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>

O formulrio de submisso de imagem tem uma particularidade em relao a formulrios que s


enviam dados de preenchimento do usurio. O protocolo HTTP estabelece que formulrios que
enviam arquivos devem conter um parmetro adicional que o enctype, que deve possui o valor
multipart/form-data. Isso faz com que o servidor aguarde por arquivos auxiliares que podem ser
divididos em mais de um pacote durante a submisso.

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.

O arquivo index.jsp passar a ter o seguinte cdigo no corpo da pgina:


Cdigo 7: index.jsp
1 <%@ t a g l i b u r i = " h t t p : / / j a v a . s u n . com / j s p / j s t l / c o r e " p r e f i x = " c " %>
2 <c : i f t e s t = " $ { u s u a r i o == n u l l } " >
3 < 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 " / >
4 </ c : if>
5 <c : i f t e s t = " $ { u s u a r i o ! = n u l l } " >
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 / menu . j s p " / >
7 < 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 " / >
8 </ c : if>

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

Fig. 2: Formulrio de Login

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.

3 Estrutura para gerenciamento de Imagens

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.

A classe Imagem foi definida da seguinte forma:


Cdigo 9: Imagem.java
1 p u b l i c c l a s s Imagem {
2 p r i v a t e long id ;

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.

Seguem os mtodos implementados na classe ImagemDAO. Apesar da implementao dos mtodos


nos cdigos disponveis utilizar JDBC, o cdigo funcionar normalmente se a interface da classe for
mantida e as implementaes substitudas por algum framework, por exemplo: o Hibernate.
Cdigo 10: ImagemDAO.java
1 p u b l i c c l a s s ImagemDAO {
2
3 p u b l i c s t a t i c v o i d s a l v a r I m a g e m ( Imagem img ) {}
4
5 p u b l i c s t a t i c v o i d e x c l u i r I m a g e m ( l o n g i d ) {}
6

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.

4 Construo do servlet Upload

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 }

O servlet Upload precisar fazer uma sequncia de aes:

a) Verificar se existe usurio logado


b) Verificar se veio um arquivo
c) Ler dados dos campos do formulrio
d) Copiar o arquivo para um endereo especfico
e) Instanciar um objeto da classe e gravar no Banco

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

8 t r y ( P r i n t W r i t e r out = response . getWriter ( ) ) {


9 HttpSession session = request . getSession () ;
10 Part p a r t f i l e = request . getPart ( " arquivo " ) ;
11 / / V e r i f i c a s e tem alguem l o g a d o e s e um a r q u i v o f o i e n v i a d o
12 i f ( p a r t f i l e ! = n u l l && 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 ) {
13 / / obtem d a d o s do f o r m u l a r i o
14 String tipo = request . getParameter ( " tipo " ) ;
15 String descricao=request . getParameter ( " descricao " ) ;
16 / / g e r a um e n d e r e c o p a r a o a r q u i v o
17 / / e s t e d i r e t o r i o d e v e e x i s t i r no s e r v i d o r
18 S t r i n g e n d e r e c o = " c : \ \ web \ \ a r q u i v o s \ \ " ;
19 / / g e r a um novo nome p r o a r q u i v o combinando
20 / / a h o r a em m i l i s e g u n d o s no s e r v i d o r com o nome
21 / / a n t i g o p a r a e v i t a r nomes r e d u n d a n t e s
22 S t r i n g nome = C a l e n d a r . g e t I n s t a n c e ( ) . g e t T i m e I n M i l l i s ( ) + g e t F i l e N a m e (
partfile ) ;
23 e n d e r e c o += nome ;
24 / / 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
25 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 ) ;
26 / / 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
27 entrada = p a r t f i l e . getInputStream () ;
28 / / 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
29 b y t e b y t e s [ ] = new b y t e [ 1 0 2 4 ] ;
30 i n t t = 0 , l e i t u r a =0;
31 / / 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
32 w h i l e ( ( t = e n t r a d a . r e a d ( b y t e s ) ) != 1) {
33 l e i t u r a += t ;
34 saida . write ( bytes , 0 , t ) ;
35 }
36 / / s a l v a o o b j e t o no b a n c o
37 ImagemDAO . s a l v a r I m a g e m ( new Imagem ( e n d e r e c o , d e s c r i c a o ) ) ;
38 s e s s i o n . s e t A t t r i b u t e ( " mensagem " , " A r q u i v o s a l v o " ) ;
39 }
40 i f ( e n t r a d a != n u l l ) {
41 entrada . close () ;
42 saida . close () ;
43 }
44 response . sendRedirect ( " index . jsp " ) ;
45 }
46 }

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.

Assim, as seguintes linhas definem o nome do arquivo:


Cdigo 15: Upload.java
1 S t r i n g e n d e r e c o = " c : \ \ web \ \ a r q u i v o s \ \ " ;
2 S t r i n g nome = C a l e n d a r . g e t I n s t a n c e ( ) . g e t T i m e I n M i l l i s ( ) + g e t F i l e N a m e ( p a r t f i l e ) ;
3 e n d e r e c o += nome ;

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.

5 Gerenciamento de Imagens: visualizao e excluso

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.

Segue o cdigo da pgina listaImagens.jsp que ficar no diretrio "auxiliares":


Cdigo 17: listaImagens.jsp
1 <table>
2 < j s p : u s e B e a n i d = " dao " c l a s s = " p e r s i s t e n c i a . ImagemDAO" / >
3 <c : f o r E a c h i t e m s = " $ { dao . i m a g e n s } " v a r = " img " >
4 <tr>
5 <td>
6 <a h r e f = " i n d e x . j s p ? p=1&img=$ { img . g e t I d ( ) } " >$ { img . g e t D e s c r i c a o ( ) }< / a >
7 </ td>
8 <td>
9 <a h r e f = " e x c l u i r ? i d =$ { img . g e t I d ( ) } " > e x c l u i r < / a >
10 </ td>
11 </ tr>
12 < / c : forEach>
13 </ table>

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

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 : if>

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.

Fig. 3: Pgina com Lista de Imagens

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.

Usualmente, o mtodo contentType do objeto response no mtodo processRequest "setado"com


o valor "text/html;charset=UTF-8", indicando que ser retornado um arquivo HTML. Agora vamos
configurar o servlet para que o cliente saiba que receber uma imagem utilizando o valor "image/jpeg".
Alm disso, o objeto out dentro do try sempre era do tipo PrintWriter, que permitia a gravao de
strings. Para retornar arquivos, ele deve ser do tipo OutputStream. Feitas essas configuraes, o
servlet deve executar as seguintes aes:

verificar se existe usurio logado


recuperar imagem
copia bytes da imagem para o objeto out
encerrar a gravao

Segue o mtodo processRequest do servlet Ver:


Cdigo 20: 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 ( " image / j p e g " ) ;
4 t r y ( OutputStream out = response . getOutputStream ( ) ) {
5 / / r e c u p e r a o b j e t o de s e s s a o
6 HttpSession session = request . getSession () ;
7 / / s e nao t i v e r ninguem l o g a d o r e t o r n a um e r r o 404
8 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 ) {
9 r e s p o n s e . s e n d E r r o r ( H t t p S e r v l e t R e s p o n s e . SC_NOT_FOUND) ;
10 }
11 / / r e c u p e r a imagem p o r i d
12 l o n g i d = Long . p a r s e L o n g ( r e q u e s t . g e t P a r a m e t e r ( " i d " ) ) ;
13 Imagem img = ImagemDAO . r e c u p e r a r I m a g e m ( i d ) ;
14 / / c r i a um s t r e a m p a r a l e r a imagem
15 I n p u t S t r e a m i n = new F i l e I n p u t S t r e a m ( new F i l e ( img . g e t E n d e r e c o ( ) ) ) ;
16 / / c o p i a o s b y t e s da imagem na s a i d a
17 b y t e b y t e s [ ] = new b y t e [ 1 0 2 4 ] ;
18 int leitura ;
19 w h i l e ( ( l e i t u r a = i n . r e a d ( b y t e s ) ) != 1) {
20 out . write ( bytes , 0 , l e i t u r a ) ;
21 }
22 / / f e c h a o s b u f f e r s de l e i t u r a e e s c r i t a
23 in . close () ;
24 out . close ( ) ;
25 }
26 }

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>

Sua pgina deve ficar como mostra a figura 4.

Fig. 4: Visualizao final da pgina

13