Servlet Upload File e Download File são tarefas comuns em aplicações web java. Como tenho escrito bastante sobre servlets java recentemente, pensei em fornecer um exemplo prático de upload de arquivo para o servidor usando servlet e depois realizar o download do servidor para o cliente.
Servlet Upload File
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 enviar o arquivo, nosso programa servlet enviará o 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 motivos de segurança, o usuário não receberá a URL direta para 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 terá a aparência mostrada na imagem abaixo. Vamos examinar todos os componentes de nossa aplicação web e entender a implementação.
Página HTML para fazer upload de arquivo Java para o servidor
Podemos enviar um arquivo para o servidor enviando uma solicitação de postagem para o servlet e enviando o formulário. Não podemos usar o método GET para fazer upload de arquivo. Outro ponto a ser observado é que enctype do formulário deve ser multipart/form-data. Para selecionar um arquivo do sistema de arquivos do usuário, precisamos usar o elemento input com type como file. Portanto, podemos ter uma página HTML simples index.html para fazer upload de arquivo como:
<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 de arquivo
Precisamos armazenar o arquivo em algum diretório no servidor, podemos ter esse diretório codificado no programa, mas para melhor flexibilidade, manteremos configurável no arquivo de descrição de implantação de parâmetros de contexto. Também adicionaremos nossa página HTML de upload de arquivo à 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 localização de upload de arquivo
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 é inicializado. Podemos definir a localização do diretório absoluto e o objeto File como atributo de contexto a ser utilizado por outros servlets. O código de implementação do nosso ServletContextListener é semelhante ao seguinte.
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) {
// fazer limpeza, se necessário
}
}
Servlet 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 será necessário 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 nosso projeto estamos utilizando a versão 1.3, 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 carregado. Para escrever o arquivo em um diretório, tudo o que precisamos fazer é criar um objeto File e passá-lo como argumento para o método write() do FileItem. Uma vez que o objetivo do servlet é fazer upload de arquivos, vamos substituir o método init() para inicializar a instância do objeto DiskFileItemFactory
do servlet. Usaremos este objeto na implementação do método doPost() para fazer o upload do arquivo para o diretório do servidor. Uma vez que o arquivo é carregado com sucesso, enviaremos uma resposta ao cliente com 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 arquivos, primeiro abriremos o InputStream para o arquivo e usaremos o método ServletContext.getMimeType() para obter o tipo MIME do arquivo e definir 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”. Uma vez feita a configuração da resposta, podemos ler o conteúdo do arquivo do InputStream e escrevê-lo no ServletOutputStream e, em seguida, enviar a saída para o cliente. Nossa implementação final do servlet UploadDownloadFileServlet parece com abaixo.
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 de Arquivo do Servlet
Você pode baixar o arquivo Apache Commons IO jar e o arquivo Apache Commons FileUpload jar a partir dos URLs abaixo. https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgi https://commons.apache.org/proper/commons-io/download_io.cgi
Baixar Projeto de Exemplo de Upload de Arquivo do Servlet
Confira o próximo artigo da série sobre Tratamento de Exceções de Servlet.
Source:
https://www.digitalocean.com/community/tutorials/servlet-upload-file-download-example