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.separatorconcatenaçõ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/filesque 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 DefaultServletmanipule, tudo o que você basicamente precisa fazer no Tomcat é adicionar o seguinte elemento Context à tag /conf/server.xmlinside <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 Servletpara isto que, basicamente, apenas recebe uma InputStreamdo arquivo no sabor de, por exemplo, FileInputStreame escreve-o para o OutputStreamdo HttpServletResponse.
Na resposta, você deve definir o Content-Typecabeçalho para que o cliente saiba qual aplicativo associar ao arquivo fornecido. E você deve definir o Content-Lengthcabeçalho para que o cliente possa calcular o progresso do download, caso contrário, será desconhecido. E, você deve definir o Content-Dispositioncabeçalho como attachmentse 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-patternde, 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: