Eu já vi algumas sugestões, como ter o diretório de imagens como um link simbólico apontando para um diretório fora do contêiner da web, mas será que essa abordagem funcionará nos ambientes Windows e * nix?
Se você seguir as regras do caminho do sistema de arquivos * nix (ou seja, você usa barras invertidas exclusivamente como em /path/to/files
), ele também funcionará no Windows sem a necessidade de mexer nas File.separator
concatenações feias de strings. No entanto, ele seria verificado apenas no mesmo disco de trabalho a partir de onde esse comando foi chamado. Então, se Tomcat é, por exemplo, instalado em C:
seguida, o /path/to/files
que realmente apontam para C:\path\to\files
.
Se todos os arquivos estão localizados fora do aplicativo da Web e você deseja que o Tomcat os DefaultServlet
manipule, tudo o que você basicamente precisa fazer no Tomcat é adicionar o seguinte elemento Context à tag /conf/server.xml
inside <Host>
:
<Context docBase="/path/to/files" path="/files" />
Dessa forma, eles estarão acessíveis através http://example.com/files/...
. O exemplo de configuração do GlassFish / Payara pode ser encontrado aqui e o exemplo de configuração do WildFly pode ser encontrado aqui .
Se você quer ter controle sobre a leitura / escrita de arquivos si mesmo, então você precisa criar um Servlet
para isto que, basicamente, apenas recebe uma InputStream
do arquivo no sabor de, por exemplo, FileInputStream
e escreve-o para o OutputStream
do HttpServletResponse
.
Na resposta, você deve definir o Content-Type
cabeçalho para que o cliente saiba qual aplicativo associar ao arquivo fornecido. E você deve definir o Content-Length
cabeçalho para que o cliente possa calcular o progresso do download, caso contrário, será desconhecido. E, você deve definir o Content-Disposition
cabeçalho como attachment
se desejar uma caixa de diálogo Salvar como , caso contrário, o cliente tentará exibi-lo em linha. Por fim, basta escrever o conteúdo do arquivo no fluxo de saída da resposta.
Aqui está um exemplo básico desse servlet:
@WebServlet("/files/*")
public class FileServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
Quando mapeado em um url-pattern
de, por exemplo /files/*
, você pode chamá-lo por http://example.com/files/image.png
. Dessa forma, você pode ter mais controle sobre as solicitações do que as solicitações DefaultServlet
, como fornecer uma imagem padrão ( if (!file.exists()) file = new File("/path/to/files", "404.gif")
ou seja ). Também request.getPathInfo()
é preferível usar o acima, request.getParameter()
porque é mais amigável ao SEO e, caso contrário, o IE não escolherá o nome do arquivo correto durante o Salvar como .
Você pode reutilizar a mesma lógica para servir arquivos do banco de dados. Simplesmente substitua new FileInputStream()
por ResultSet#getInputStream()
.
Espero que isto ajude.
Veja também: