He visto algunas sugerencias, como que el directorio de imágenes sea un enlace simbólico que apunta a un directorio fuera del contenedor web, pero ¿funcionará este enfoque en entornos Windows y * nix?
Si cumple las reglas de ruta del sistema de archivos * nix (es decir, utiliza barras inclinadas exclusivamente como en /path/to/files), funcionará también en Windows sin la necesidad de jugar con feos File.separatorconcatenaciones de cadenas. Sin embargo, solo se escanearía en el mismo disco de trabajo desde el que se invoca este comando. Entonces, si Tomcat está instalado, por ejemplo, C:entonces /path/to/filesrealmente apuntaría a C:\path\to\files.
Si todos los archivos se encuentran fuera de la aplicación web y desea tener Tomcat DefaultServletpara manejarlos, entonces todo lo que necesita hacer básicamente en Tomcat es agregar el siguiente elemento de Contexto a la etiqueta /conf/server.xmlinterna <Host>:
<Context docBase="/path/to/files" path="/files" />
De esta manera serán accesibles a través de http://example.com/files/.... El ejemplo de configuración de GlassFish / Payara se puede encontrar aquí y el ejemplo de configuración de WildFly se puede encontrar aquí .
Si desea tener control sobre la lectura / escritura de archivos usted mismo, debe crear un archivo Servletpara esto, que básicamente solo obtiene una InputStreammuestra del archivo, por ejemplo, FileInputStreamy lo escribe en OutputStreamel HttpServletResponse.
En la respuesta, debe establecer el Content-Typeencabezado para que el cliente sepa qué aplicación asociar con el archivo proporcionado. Y, debe configurar el Content-Lengthencabezado para que el cliente pueda calcular el progreso de la descarga, de lo contrario será desconocido. Y debe establecer el Content-Dispositionencabezado en attachmentsi desea un cuadro de diálogo Guardar como , de lo contrario, el cliente intentará mostrarlo en línea. Finalmente, solo escriba el contenido del archivo en la secuencia de salida de respuesta.
Aquí hay un ejemplo básico de tal 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());
}
}
Cuando se asigna en un url-patternde, por ejemplo /files/*, puede llamarlo por http://example.com/files/image.png. De esta manera, puede tener más control sobre las solicitudes que las que DefaultServlettiene, como proporcionar una imagen predeterminada (es decir, más if (!file.exists()) file = new File("/path/to/files", "404.gif")o menos). También request.getPathInfo()se prefiere usar el anterior request.getParameter()porque es más compatible con SEO y, de lo contrario, IE no elegirá el nombre de archivo correcto durante Guardar como .
Puede reutilizar la misma lógica para servir archivos desde la base de datos. Simplemente reemplace new FileInputStream()por ResultSet#getInputStream().
Espero que esto ayude.
Ver también: