Servlet Upload File e Download File são tarefas comuns em aplicações web Java. Como tenho escrito muito sobre servlets Java recentemente, pensei em fornecer um exemplo prático de upload de arquivo para o servidor usando servlet e em seguida fazer o download do servidor para o cliente.
Upload de Arquivo com Servlet
Nosso caso de uso é fornecer uma página HTML simples onde o cliente pode selecionar um arquivo local para ser enviado ao servidor. Ao enviar a solicitação para fazer o upload do arquivo, nosso programa servlet fará o upload do arquivo para um diretório no servidor e, em seguida, fornecerá a URL pela qual o usuário pode fazer o download do arquivo. Por razões de segurança, o usuário não receberá a URL direta para fazer o download do arquivo; em vez disso, será fornecido um link para baixar o arquivo, e nosso servlet processará a solicitação e enviará o arquivo ao usuário. Criaremos um projeto web dinâmico no Eclipse e a estrutura do projeto será semelhante à imagem abaixo. Vamos analisar todos os componentes de nossa aplicação web e entender a implementação.
Página HTML para Upload de Arquivos em Java para o Servidor
Podemos fazer o upload de um arquivo para o servidor enviando uma solicitação POST para o servlet e enviando o formulário. Não podemos usar o método GET para fazer upload de arquivos. Outro ponto a ser observado é que o enctype do formulário deve ser multipart/form-data. Para selecionar um arquivo no sistema de arquivos do usuário, precisamos usar o elemento input com type como file. Assim, podemos ter uma página HTML simples chamada index.html para fazer upload de arquivos:
<html>
<head></head>
<body>
<form action="UploadDownloadFileServlet" method="post" enctype="multipart/form-data">
Select File to Upload:<input type="file" name="fileName">
<br>
<input type="submit" value="Upload">
</form>
</body>
</html>
Localização do Arquivo no Servidor para Upload
Precisamos armazenar o arquivo em algum diretório no servidor. Podemos ter esse diretório codificado no programa, mas para uma melhor flexibilidade, o manteremos configurável nos parâmetros de contexto do descritor de implantação. Também adicionaremos nossa página HTML de upload de arquivos à lista de arquivos de boas-vindas. Nosso arquivo web.xml ficará assim:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletFileUploadDownloadExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>tempfile.dir</param-name>
<param-value>tmpfiles</param-value>
</context-param>
</web-app>
ServletContextListener para a Localização do Upload de Arquivos
Como precisamos ler o parâmetro de contexto para a localização do arquivo e criar um objeto File a partir dele, podemos escrever um ServletContextListener para fazer isso quando o contexto for inicializado. Podemos definir a localização do diretório absoluto e o objeto File como atributo de contexto a ser usado por outros servlets. Nosso código de implementação do ServletContextListener é semelhante ao abaixo.
package com.journaldev.servlet;
import java.io.File;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class FileLocationContextListener implements ServletContextListener {
public void contextInitialized(ServletContextEvent servletContextEvent) {
String rootPath = System.getProperty("catalina.home");
ServletContext ctx = servletContextEvent.getServletContext();
String relativePath = ctx.getInitParameter("tempfile.dir");
File file = new File(rootPath + File.separator + relativePath);
if(!file.exists()) file.mkdirs();
System.out.println("File Directory created to be used for storing files");
ctx.setAttribute("FILES_DIR_FILE", file);
ctx.setAttribute("FILES_DIR", rootPath + File.separator + relativePath);
}
public void contextDestroyed(ServletContextEvent servletContextEvent) {
//faça a limpeza se necessário
}
}
Servidor de Upload e Download de Arquivos
Atualização: As especificações do Servlet 3 adicionaram suporte para fazer upload de arquivos no servidor na API, então não precisaremos usar nenhuma API de terceiros. Por favor, confira Upload de Arquivo Servlet 3. Para o upload de arquivos, vamos utilizar a utilidade Apache Commons FileUpload. Para o nosso projeto, estamos usando a versão 1.3. O FileUpload depende do arquivo Apache Commons IO, então precisamos colocar ambos no diretório lib do projeto, como você pode ver na imagem acima da estrutura do projeto. Vamos utilizar a fábrica DiskFileItemFactory, que fornece um método para analisar o objeto HttpServletRequest e retornar uma lista de FileItem. FileItem fornece métodos úteis para obter o nome do arquivo, nome do campo no formulário, tamanho e detalhes do tipo de conteúdo do arquivo que precisa ser enviado. Para escrever o arquivo em um diretório, tudo que precisamos fazer é criar um objeto File e passá-lo como argumento para o método write() do FileItem. Como o objetivo principal do servlet é enviar o arquivo, vamos substituir o método init() para inicializar a instância do objeto DiskFileItemFactory
do servlet. Vamos usar este objeto na implementação do método doPost() para enviar o arquivo para o diretório do servidor. Uma vez que o arquivo é enviado com sucesso, enviaremos uma resposta ao cliente com a URL para baixar o arquivo. Como os links HTML usam o método GET, vamos anexar o parâmetro para o nome do arquivo na URL e podemos utilizar o mesmo método doGet() do servlet para implementar o processo de download do arquivo. Para implementar o servlet de download de arquivo, primeiro abriremos o InputStream para o arquivo e usaremos o método ServletContext.getMimeType() para obter o tipo MIME do arquivo e defini-lo como tipo de conteúdo da resposta. Também precisaremos definir o comprimento do conteúdo da resposta como o comprimento do arquivo. Para garantir que o cliente entenda que estamos enviando o arquivo como resposta, precisamos definir o cabeçalho “Content-Disposition” com o valor “attachment; filename=“fileName”. Depois de configurar a resposta, podemos ler o conteúdo do arquivo do InputStream e escrevê-lo no ServletOutputStream e depois enviar a saída para o cliente. Nossa implementação final do servlet UploadDownloadFileServlet parece com o seguinte.
package com.journaldev.servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
@WebServlet("/UploadDownloadFileServlet")
public class UploadDownloadFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private ServletFileUpload uploader = null;
@Override
public void init() throws ServletException{
DiskFileItemFactory fileFactory = new DiskFileItemFactory();
File filesDir = (File) getServletContext().getAttribute("FILES_DIR_FILE");
fileFactory.setRepository(filesDir);
this.uploader = new ServletFileUpload(fileFactory);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("fileName");
if(fileName == null || fileName.equals("")){
throw new ServletException("File Name can't be null or empty");
}
File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileName);
if(!file.exists()){
throw new ServletException("File doesn't exists on server.");
}
System.out.println("File location on server::"+file.getAbsolutePath());
ServletContext ctx = getServletContext();
InputStream fis = new FileInputStream(file);
String mimeType = ctx.getMimeType(file.getAbsolutePath());
response.setContentType(mimeType != null? mimeType:"application/octet-stream");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
ServletOutputStream os = response.getOutputStream();
byte[] bufferData = new byte[1024];
int read=0;
while((read = fis.read(bufferData))!= -1){
os.write(bufferData, 0, read);
}
os.flush();
os.close();
fis.close();
System.out.println("File downloaded at client successfully");
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if(!ServletFileUpload.isMultipartContent(request)){
throw new ServletException("Content type is not multipart/form-data");
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.write("<html><head></head><body>");
try {
List<FileItem> fileItemsList = uploader.parseRequest(request);
Iterator<FileItem> fileItemsIterator = fileItemsList.iterator();
while(fileItemsIterator.hasNext()){
FileItem fileItem = fileItemsIterator.next();
System.out.println("FieldName="+fileItem.getFieldName());
System.out.println("FileName="+fileItem.getName());
System.out.println("ContentType="+fileItem.getContentType());
System.out.println("Size in bytes="+fileItem.getSize());
File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileItem.getName());
System.out.println("Absolute Path at server="+file.getAbsolutePath());
fileItem.write(file);
out.write("File "+fileItem.getName()+ " uploaded successfully.");
out.write("<br>");
out.write("<a href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">Download "+fileItem.getName()+"</a>");
}
} catch (FileUploadException e) {
out.write("Exception in uploading file.");
} catch (Exception e) {
out.write("Exception in uploading file.");
}
out.write("</body></html>");
}
}
A execução de exemplo do projeto é mostrada nas imagens abaixo.
Baixar Projeto de Upload e Download de Arquivo Servlet
Você pode baixar o arquivo jar do Apache Commons IO e o arquivo jar do Apache Commons FileUpload nos seguintes URLs. https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi https://commons.apache.org/proper/commons-io/download_io.cgi
Baixar Exemplo de Projeto de Upload e Download de Arquivo Servlet
Confira o próximo artigo da série sobre Tratamento de Exceções em Servlets.
Source:
https://www.digitalocean.com/community/tutorials/servlet-upload-file-download-example