Solución:
Precisamente, tiene que ser accesible mediante una URL pública. Por lo tanto, la <img src>
debe en última instancia referir un http://
URI, no algo como un file://
URI más o menos. En última instancia, la fuente HTML se ejecuta en la máquina del usuario final y el navegador web descarga las imágenes individualmente durante el análisis de la fuente HTML. Cuando el navegador web encuentra un file://
URI como C:pathtoimage.png
, luego buscará la imagen en el propio sistema de archivos del disco local del usuario final en lugar del del servidor web. Obviamente, esto no funcionará si el navegador web se ejecuta en una máquina físicamente diferente a la del servidor web.
Hay varias formas de lograrlo:
-
Si tiene control total sobre la carpeta de imágenes, simplemente suelte la carpeta con todas las imágenes, p. Ej.
/images
directamente en la carpeta de implementación de servletcontainer, como el/webapps
carpeta en el caso de Tomcat y/domains/domain1/applications
carpeta en caso de GlassFish. No es necesaria ninguna configuración adicional.
-
O agregue un nuevo contexto de aplicación web al servidor que apunte a la ubicación absoluta del sistema de archivos de disco de la carpeta con esas imágenes. La forma de hacerlo depende del recipiente utilizado. Los siguientes ejemplos asumen que las imágenes están ubicadas en
/path/to/images
y que le gustaría acceder a ellos a través de http: //…/images.En el caso de Tomcat, agregue la siguiente entrada nueva a Tomcat’s
/conf/server.xml
dentro<Host>
:<Context docBase="/path/to/images" path="/images" />
En el caso de GlassFish, agregue la siguiente entrada a
/WEB-INF/glassfish-web.xml
:<property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
En el caso de WildFly, agregue la siguiente entrada dentro
<host name="default-host">
de/standalone/configuration/standalone.xml
…<location name="/images" handler="images-content" />
… y más abajo en
<handlers>
entrada de la mismísima<subsystem>
como anteriormente<location>
:<file name="images-content" path="/path/to/images" />
-
O crea un
Servlet
que transmite la imagen del disco a la respuesta:@WebServlet("/images/*") public class ImageServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String filename = request.getPathInfo().substring(1); File file = new File("/path/to/images", filename); response.setHeader("Content-Type", getServletContext().getMimeType(filename)); response.setHeader("Content-Length", String.valueOf(file.length())); response.setHeader("Content-Disposition", "inline; filename="" + filename + """); Files.copy(file.toPath(), response.getOutputStream()); } }
Si utiliza OmniFaces, entonces el
FileServlet
puede ser útil, ya que también tiene en cuenta las solicitudes de rango, almacenamiento en caché y encabezado.
-
O utilice OmniFaces
<o:graphicImage>
que admite una propiedad de frijol que regresabyte[]
oInputStream
:@Named @ApplicationScoped public class Bean { public InputStream getImage(String filename) { return new FileInputStream(new File("/path/to/images", filename)); } }
-
O usa PrimeFaces
<p:graphicImage>
que admite un método de frijol que devuelve PrimeFaces específicoStreamedContent
.@Named @ApplicationScoped public class Bean { public StreamedContent getImage() throws IOException { FacesContext context = FacesContext.getCurrentInstance(); if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) { // So, we're rendering the view. Return a stub StreamedContent so that it will generate right URL. return new DefaultStreamedContent(); } else { // So, browser is requesting the image. Return a real StreamedContent with the image bytes. String filename = context.getExternalContext().getRequestParameterMap().get("filename"); return new DefaultStreamedContent(new FileInputStream(new File("/path/to/images", filename))); } } }
Para la primera forma y los enfoques de Tomcat y WildFly en la segunda forma, las imágenes estarán disponibles en http://example.com/images/filename.ext y, por lo tanto, serán referenciables en HTML sin formato de la siguiente manera
<img src="https://foroayuda.es/images/filename.ext" />
Para el enfoque GlassFish de segunda y tercera forma, las imágenes estarán disponibles en http://example.com/context/images/filename.ext y, por lo tanto, se podrán consultar en HTML sin formato de la siguiente manera
<img src="https://foroayuda.es/#{request.contextPath}/images/filename.ext" />
o en JSF de la siguiente manera (la ruta de contexto se antepone automáticamente)
<h:graphicImage value="https://foroayuda.es/images/filename.ext" />
Para el enfoque de OmniFaces en la cuarta forma, consúltelo de la siguiente manera
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
Para el enfoque PrimeFaces en la quinta forma, haga referencia a él de la siguiente manera:
<p:graphicImage value="#{bean.image}">
<f:param name="filename" value="filename.ext" />
</p:graphicImage>
Tenga en cuenta que el ejemplo #{bean}
es @ApplicationScoped
ya que básicamente representa un servicio sin estado. También puedes hacerlo @RequestScoped
, pero luego el bean se volvería a crear en cada solicitud, por nada. No puedes hacerlo @ViewScoped
, porque en el momento en que el navegador necesita descargar la imagen, el servidor no crea una página JSF. Tu puedes hacerlo @SessionScoped
, pero luego se guarda en la memoria, por nada.
Ver también:
- Forma recomendada de guardar archivos cargados en una aplicación de servlet
- La forma más sencilla de servir datos estáticos desde fuera del servidor de aplicaciones en una aplicación web Java
- Plantilla abstracta para un servlet de recursos estáticos (compatible con el almacenamiento en caché HTTP)
- Mostrar imagen como byte[] de la base de datos como imagen gráfica en la página JSF
- Muestre la imagen dinámica de la base de datos con p: graphicImage y StreamedContent
- ¿Cómo elegir el alcance de frijol correcto?
Para lograr lo que necesita usando <h:graphicImage>
o <img>
etiquetas, debe crear un alias de Tomcat v7 para asignar la ruta externa al contexto de su aplicación web.
Para hacerlo, deberá especificar el contexto de su aplicación web. Lo más fácil sería definir un archivo META-INF / context.xml con el siguiente contenido:
<Context path="/myapp" aliases="/images=/path/to/external/images">
</Context>
Luego, después de reiniciar su servidor Tomcat, puede acceder a sus archivos de imágenes usando <h:graphicImage
> o <img>
etiquetas de la siguiente manera:
<h:graphicImage value="/images/my-image.png">
o
<img src="https://foroayuda.es/myapp/images/my-image.png">
* Tenga en cuenta que la ruta de contexto es necesaria para la etiqueta pero no para la
Otro enfoque posible si no necesita que las imágenes estén disponibles a través del método HTTP GET, podría ser usar Primefaces <p:fileDownload>
etiqueta (usando commandLink o Botón de comando etiquetas – Método HTTP POST).
En tu Facelet:
<h:form>
<h:commandLink id="downloadLink" value="Download">
<p:fileDownload value="#{fileDownloader.getStream(file.path)}" />
</h:commandLink>
</h:form
En tu frijol:
@ManagedBean
@ApplicationScope
public class FileDownloader {
public StreamedContent getStream(String absPath) throws Exception {
FileInputStream fis = new FileInputStream(absPath);
BufferedInputStream bis = new BufferedInputStream(fis);
StreamedContent content = new DefaultStreamedContent(bis);
return content;
}
}
}