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.separator
concatenaciones 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/files
realmente apuntaría a C:\path\to\files
.
Si todos los archivos se encuentran fuera de la aplicación web y desea tener Tomcat DefaultServlet
para manejarlos, entonces todo lo que necesita hacer básicamente en Tomcat es agregar el siguiente elemento de Contexto a la etiqueta /conf/server.xml
interna <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 Servlet
para esto, que básicamente solo obtiene una InputStream
muestra del archivo, por ejemplo, FileInputStream
y lo escribe en OutputStream
el HttpServletResponse
.
En la respuesta, debe establecer el Content-Type
encabezado para que el cliente sepa qué aplicación asociar con el archivo proporcionado. Y, debe configurar el Content-Length
encabezado para que el cliente pueda calcular el progreso de la descarga, de lo contrario será desconocido. Y debe establecer el Content-Disposition
encabezado en attachment
si 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-pattern
de, 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 DefaultServlet
tiene, 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: