Exemplo de download de arquivo em um servlet

Exemplo de download de arquivo em um servlet

 1. Visão geral

Um recurso comum dos aplicativos da web é a capacidade de baixar arquivos.

Neste tutorial,we’ll cover a simple example of creating a downloadable file and serving it from a Java Servlet application.

O arquivo que estamos usando será dos recursos do aplicativo da web.

2. Dependências do Maven

If using Java EE, then we wouldn’t need to add any dependencies. No entanto, se estivermos usando Java SE, precisaremos da dependência javax.servlet-api:


    javax.servlet
    javax.servlet-api
    4.0.1
    provided

A versão mais recente da dependência pode ser encontradahere.

3. Servlet

Vamos dar uma olhada no código primeiro e depois descobrir o que está acontecendo:

@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
    private final int ARBITARY_SIZE = 1048;

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
      throws ServletException, IOException {

        resp.setContentType("text/plain");
        resp.setHeader("Content-disposition", "attachment; filename=sample.txt");

        try(InputStream in = req.getServletContext().getResourceAsStream("/WEB-INF/sample.txt");
          OutputStream out = resp.getOutputStream()) {

            byte[] buffer = new byte[ARBITARY_SIZE];

            int numBytesRead;
            while ((numBytesRead = in.read(buffer)) > 0) {
                out.write(buffer, 0, numBytesRead);
            }
        }
    }
}

3.1. Ponto final da solicitação

A anotação@WebServlet(“/download”) marca a classeDownloadServlet para atender às solicitações direcionadas ao ponto de envio“/download” .

Como alternativa, podemos fazer isso descrevendo o mapeamento no arquivo web.xml.

3.2. RespostaContent-Type

O objetoHttpServletResponse tem um método chamadosetContentType que podemos usar para definir o cabeçalhoContent-Type da resposta HTTP.

Content-Type é o nome histórico da propriedade do cabeçalho. Outro nome era o tipo MIME (Multipurpose Internet Mail Extensions). Agora, simplesmente nos referimos ao valor como o Tipo de mídia.

This value could be “application/pdf”, “text/plain”, “text/html”, “image/jpg”, etc., a lista oficial é mantida pela Internet Assigned Numbers Authority (IANA) e pode ser encontradahere.

Para o nosso exemplo, estamos usando um arquivo de texto simples. The Content-Type for a text file is “text/plain”.

3.3. RespostaContent-Disposition

Definir o sheaderContent-Disposition no objeto de resposta informa ao navegador como lidar com o arquivo que está acessando.

Os navegadores entendem o uso deContent-Disposition como uma convenção, mas na verdade não faz parte do padrão HTTP. W3 tem um memorando sobre o uso deContent-Disposition disponível para lerhere.

Os valores deContent-Disposition para o corpo principal de uma resposta serão "embutidos" (para o conteúdo da página da web a ser renderizado) ou "anexo" (para um arquivo para download).

Se não for especificado, oContent-Disposition padrão é “embutido”.

Usando um parâmetro de cabeçalho opcional, podemos especificar o nome do arquivo "sample.txt".

Alguns navegadores baixam imediatamente o arquivo usando o nome de arquivo fornecido e outros mostram uma caixa de diálogo de download contendo o nosso valor predefinido.

A ação exata tomada dependerá do navegador.

3.4. Leitura de arquivo e gravação no fluxo de saída

Nas linhas restantes do código, pegamos oServletContext da solicitação e o usamos para obter o arquivo em “/WEB-INF/sample.txt”.

UsandoHttpServletResponse #getOutputStream(), lemos a partir do fluxo de entrada do recurso e gravamos emOutputStream da resposta.

O tamanho da matriz de bytes que usamos é arbitrário. Podemos decidir o tamanho com base na quantidade de memória que é razoável alocar para passar os dados deInputStream paraOutputStream; quanto menor o nuber, mais voltas; quanto maior o número, maior o uso de memória.

Este ciclo continua até quenumByteRead seja 0, o que indica o fim do arquivo.

3.5. Fechar e lavar

As instâncias deStream devem ser fechadas após o uso para liberar quaisquer recursos que estejam retendo no momento. As instâncias deWriter também devem ser liberadas para gravar quaisquer bytes restantes no buffer em seu destino.

Usando uma instruçãotry-with-resources, o aplicativo irá automaticamenteclose qualquer instânciaAutoCloseable definida como parte da instruçãotry. Leia mais sobre try-with-resourceshere.

Usamos esses dois métodos para liberar memória, garantindo que os dados que preparamos sejam enviados de nosso aplicativo.

3.6. Baixando o arquivo

Com tudo no lugar, agora estamos prontos para executar nosso Servlet.

Agora, quando visitarmos o ponto final relativo“/download”, nosso navegador tentará fazer o download do arquivo como “simple.txt”.

4. Conclusão

Baixar um arquivo de um Servlet se torna um processo simples. O uso de fluxos nos permite distribuir os dados como bytes, e os Tipos de mídia informam ao navegador do cliente que tipo de dados esperar.

Cabe ao navegador determinar como lidar com a resposta, no entanto, podemos fornecer algumas orientações com o cabeçalhoContent-Disposition.

Todo o código neste artigo pode ser encontrado emover on GitHub.