I need to display images which reside outside of deploy folder in web application using JSF <h:graphicimage>
tag or HTML <img>
tag. How can I achieve that?
我需要使用JSF
4 个解决方案
#1
To the point, it has to be accessible by a public URL. Thus, the <img src>
must ultimately refer a http://
URI, not something like a file://
URI or so. Ultimately, the HTML source is executed at enduser's machine and images are downloaded individually by the webbrowser during parsing the HTML source. When the webbrowser encounters a file://
URI such as C:\path\to\image.png
, then it will look in enduser's own local disk file system for the image instead of the webserver's one. This is obviously not going to work if the webbrowser runs at a physically different machine than the webserver.
到目前为止,它必须可以通过公共URL访问。因此,必须最终引用http:// URI,而不是像file:// URI那样。最终,HTML源在最终用户的机器上执行,并且在解析HTML源期间,webbrowser单独下载图像。当webbrowser遇到file:// URI(例如C:\ path \ to \ image.png)时,它将在enduser自己的本地磁盘文件系统中查找映像而不是webserver的映像。如果webbrowser在与Web服务器不同的物理机器上运行,这显然不会起作用。
There are several ways to achieve this:
有几种方法可以实现这一目标:
-
If you have full control over the images folder, then just drop the folder with all images, e.g.
/images
directly in servletcontainer's deploy folder, such as the/webapps
folder in case of Tomcat and/domains/domain1/applications
folder in case of GlassFish. No further configuration is necessary.如果您完全控制图像文件夹,则只需删除包含所有图像的文件夹,例如/ images直接在servletcontainer的deploy文件夹中,例如Tomcat的/ webapps文件夹和GlassFish的/ domains / domain1 / applications文件夹。无需进一步配置。
-
Or, add a new webapp context to the server which points to the absolute disk file system location of the folder with those images. How to do that depends on the container used. The below examples assume that images are located in
/path/to/images
and that you'd like to access them via http://.../images.或者,向服务器添加一个新的webapp上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置。怎么做取决于使用的容器。以下示例假设图像位于/ path / to / images中,并且您希望通过http://.../ images来访问它们。
In case of Tomcat, add the following new entry to Tomcat's
/conf/server.xml
inside<Host>
:如果是Tomcat,请将以下新条目添加到
内的Tomcat的/conf/server.xml中: <Context docBase="/path/to/images" path="/images" />
In case of GlassFish, add the following entry to
/WEB-INF/glassfish-web.xml
:对于GlassFish,将以下条目添加到/WEB-INF/glassfish-web.xml:
<property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
In case of WildFly, add the following entry inside
<host name="default-host">
of/standalone/configuration/standalone.xml
...如果是WildFly,请在/standalone/configuration/standalone.xml的
中添加以下条目... <location name="/images" handler="images-content" />
... and further down in
<handlers>
entry of the very same<subsystem>
as above<location>
:...并进一步在
中输入与 完全相同的 : <file name="images-content" path="/path/to/images" />
-
Or, create a
Servlet
which streams the image from disk to response:或者,创建一个Servlet,将图像从磁盘流式传输到响应:
@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()); }}
If you happen to use OmniFaces, then the
FileServlet
may be useful as it also takes into account head, caching and range requests.如果您碰巧使用OmniFaces,那么FileServlet可能很有用,因为它还会考虑头部,缓存和范围请求。
-
Or, use OmniFaces
<o:graphicImage>
which supports a bean property returningbyte[]
orInputStream
:或者,使用OmniFaces
,它支持返回byte []或InputStream的bean属性: @Named@ApplicationScopedpublic class Bean { public InputStream getImage(String filename) { return new FileInputStream(new File("/path/to/images", filename)); }}
-
Or, use PrimeFaces
<p:graphicImage>
which supports a bean method returning PrimeFaces-specificStreamedContent
.或者,使用PrimeFaces
,它支持返回PrimeFaces特定StreamedContent的bean方法。 @Named@ApplicationScopedpublic 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))); } }}
For the first way and the Tomcat and WildFly approaches in second way, the images will be available by http://example.com/images/filename.ext and thus referencable in plain HTML as follows
对于第一种方式,Tomcat和WildFly以第二种方式接近,图像将可以通过http://example.com/images/filename.ext获得,因此可以在纯HTML中按照以下方式引用
<img src="/images/filename.ext" />
For the GlassFish approach in second way and the third way, the images will be available by http://example.com/context/images/filename.ext and thus referencable in plain HTML as follows
对于第二种方式和第三种方式的GlassFish方法,图像将通过http://example.com/context/images/filename.ext提供,因此可以在纯HTML中按照以下方式进行引用:
<img src="#{request.contextPath}/images/filename.ext" />
or in JSF as follows (context path is automatically prepended)
或者在JSF中如下(上下文路径自动添加)
<h:graphicImage value="/images/filename.ext" />
For the OmniFaces approach in fourth way, reference it as follows
对于第四种方式的OmniFaces方法,请参考如下
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
For the PrimeFaces approach in fifth way, reference it as follows:
对于第五种方式的PrimeFaces方法,请参考如下:
<p:graphicImage value="#{bean.image}"> <f:param name="filename" value="filename.ext" /></p:graphicImage>
Note that the example #{bean}
is @ApplicationScoped
as it basically represents a stateless service. You can also make it @RequestScoped
, but then the bean would be recreated on every single request, for nothing. You cannot make it @ViewScoped
, because at the moment the browser needs to download the image, the server doesn't create a JSF page. You can make it @SessionScoped
, but then it's saved in memory, for nothing.
请注意,示例#{bean}是@ApplicationScoped,因为它基本上代表无状态服务。您也可以将其设为@RequestScoped,但是随后会在每个请求上重新创建bean。你无法使它成为@ViewScoped,因为目前浏览器需要下载图像,服务器不会创建一个JSF页面。你可以将其设为@SessionScoped,但它会保存在内存中,什么也不保存。
See also:
- Recommended way to save uploaded files in a servlet application
- Simplest way to serve static data from outside the application server in a Java web application
- Abstract template for a static resource servlet (supporting HTTP caching)
- Show image as byte[] from database as graphic image in JSF page
- Display dynamic image from database with p:graphicImage and StreamedContent
- How to choose the right bean scope?
建议在servlet应用程序中保存上载文件的方法
在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法
静态资源servlet的抽象模板(支持HTTP缓存)
在JSF页面中将图像作为byte []显示为图形图像
使用p:graphicImage和StreamedContent从数据库显示动态图像
如何选择合适的bean范围?
#2
In order to achieve what you need using <h:graphicImage>
or <img>
tags, you require to create a Tomcat v7 alias in order to map the external path to your web app's context.
为了使用
To do so, you will need to specify your web app's context. The easiest would be to define a META-INF/context.xml file with the following content:
为此,您需要指定Web应用程序的上下文。最简单的方法是使用以下内容定义META-INF / context.xml文件:
<Context path="/myapp" aliases="/images=/path/to/external/images"></Context>
Then after restarting your Tomcat server, you can access your images files using <h:graphicImage
> or <img>
tags as following:
然后在重新启动Tomcat服务器后,您可以使用
<h:graphicImage value="/images/my-image.png">
or
<img src="/myapp/images/my-image.png">
*Note the context path is necessary for the tag but not for the
*请注意,上下文路径是标记所必需的,但不是
Another possible approach if you don't require the images to be available through HTTP GET method, could be to use Primefaces <p:fileDownload>
tag (using commandLink or commandButton tags - HTTP POST method).
如果您不要求图像通过HTTP GET方法可用,另一种可能的方法是使用Primefaces
In your Facelet:
在你的Facelet中:
<h:form> <h:commandLink id="downloadLink" value="Download"> <p:fileDownload value="#{fileDownloader.getStream(file.path)}" /> </h:commandLink></h:form
In your bean:
在你的bean中:
@ManagedBean@ApplicationScopepublic 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; } }}
#3
In PrimeFaces you can implement your bean in this way:
在PrimeFaces中,您可以通过以下方式实现bean:
private StreamedContent image;public void setImage(StreamedContent image) { this.image = image;}public StreamedContent getImage() throws Exception { return image;}public void prepImage() throws Exception {File file = new File("/path/to/your/image.png");InputStream input = new FileInputStream(file);ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();setImage(new DefaultStreamedContent(input,externalContext.getMimeType(file.getName()), file.getName()));}
In your HTML Facelet:
在您的HTML Facelet中:
<body onload="#{yourBean.prepImage()}"></body> <p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" ></p:graphicImage>
I suggest to set the attribute cache="false" in the graphicImage component.
我建议在graphicImage组件中设置属性cache =“false”。
#4
In JSP
<img src="data:image/jpeg;base64,<%= new String(Base64.encode(Files.readAllBytes(Paths.get("C:\\temp\\A.jpg"))))%>"/>
Packages are com.sun.jersey.core.util.Base64
, java.nio.file.Paths
and java.nio.file.Files
.
包是com.sun.jersey.core.util.Base64,java.nio.file.Paths和java.nio.file.Files。
#1
To the point, it has to be accessible by a public URL. Thus, the <img src>
must ultimately refer a http://
URI, not something like a file://
URI or so. Ultimately, the HTML source is executed at enduser's machine and images are downloaded individually by the webbrowser during parsing the HTML source. When the webbrowser encounters a file://
URI such as C:\path\to\image.png
, then it will look in enduser's own local disk file system for the image instead of the webserver's one. This is obviously not going to work if the webbrowser runs at a physically different machine than the webserver.
到目前为止,它必须可以通过公共URL访问。因此,必须最终引用http:// URI,而不是像file:// URI那样。最终,HTML源在最终用户的机器上执行,并且在解析HTML源期间,webbrowser单独下载图像。当webbrowser遇到file:// URI(例如C:\ path \ to \ image.png)时,它将在enduser自己的本地磁盘文件系统中查找映像而不是webserver的映像。如果webbrowser在与Web服务器不同的物理机器上运行,这显然不会起作用。
There are several ways to achieve this:
有几种方法可以实现这一目标:
-
If you have full control over the images folder, then just drop the folder with all images, e.g.
/images
directly in servletcontainer's deploy folder, such as the/webapps
folder in case of Tomcat and/domains/domain1/applications
folder in case of GlassFish. No further configuration is necessary.如果您完全控制图像文件夹,则只需删除包含所有图像的文件夹,例如/ images直接在servletcontainer的deploy文件夹中,例如Tomcat的/ webapps文件夹和GlassFish的/ domains / domain1 / applications文件夹。无需进一步配置。
-
Or, add a new webapp context to the server which points to the absolute disk file system location of the folder with those images. How to do that depends on the container used. The below examples assume that images are located in
/path/to/images
and that you'd like to access them via http://.../images.或者,向服务器添加一个新的webapp上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置。怎么做取决于使用的容器。以下示例假设图像位于/ path / to / images中,并且您希望通过http://.../ images来访问它们。
In case of Tomcat, add the following new entry to Tomcat's
/conf/server.xml
inside<Host>
:如果是Tomcat,请将以下新条目添加到
内的Tomcat的/conf/server.xml中: <Context docBase="/path/to/images" path="/images" />
In case of GlassFish, add the following entry to
/WEB-INF/glassfish-web.xml
:对于GlassFish,将以下条目添加到/WEB-INF/glassfish-web.xml:
<property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
In case of WildFly, add the following entry inside
<host name="default-host">
of/standalone/configuration/standalone.xml
...如果是WildFly,请在/standalone/configuration/standalone.xml的
中添加以下条目... <location name="/images" handler="images-content" />
... and further down in
<handlers>
entry of the very same<subsystem>
as above<location>
:...并进一步在
中输入与 完全相同的 : <file name="images-content" path="/path/to/images" />
-
Or, create a
Servlet
which streams the image from disk to response:或者,创建一个Servlet,将图像从磁盘流式传输到响应:
@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()); }}
If you happen to use OmniFaces, then the
FileServlet
may be useful as it also takes into account head, caching and range requests.如果您碰巧使用OmniFaces,那么FileServlet可能很有用,因为它还会考虑头部,缓存和范围请求。
-
Or, use OmniFaces
<o:graphicImage>
which supports a bean property returningbyte[]
orInputStream
:或者,使用OmniFaces
,它支持返回byte []或InputStream的bean属性: @Named@ApplicationScopedpublic class Bean { public InputStream getImage(String filename) { return new FileInputStream(new File("/path/to/images", filename)); }}
-
Or, use PrimeFaces
<p:graphicImage>
which supports a bean method returning PrimeFaces-specificStreamedContent
.或者,使用PrimeFaces
,它支持返回PrimeFaces特定StreamedContent的bean方法。 @Named@ApplicationScopedpublic 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))); } }}
For the first way and the Tomcat and WildFly approaches in second way, the images will be available by http://example.com/images/filename.ext and thus referencable in plain HTML as follows
对于第一种方式,Tomcat和WildFly以第二种方式接近,图像将可以通过http://example.com/images/filename.ext获得,因此可以在纯HTML中按照以下方式引用
<img src="/images/filename.ext" />
For the GlassFish approach in second way and the third way, the images will be available by http://example.com/context/images/filename.ext and thus referencable in plain HTML as follows
对于第二种方式和第三种方式的GlassFish方法,图像将通过http://example.com/context/images/filename.ext提供,因此可以在纯HTML中按照以下方式进行引用:
<img src="#{request.contextPath}/images/filename.ext" />
or in JSF as follows (context path is automatically prepended)
或者在JSF中如下(上下文路径自动添加)
<h:graphicImage value="/images/filename.ext" />
For the OmniFaces approach in fourth way, reference it as follows
对于第四种方式的OmniFaces方法,请参考如下
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
For the PrimeFaces approach in fifth way, reference it as follows:
对于第五种方式的PrimeFaces方法,请参考如下:
<p:graphicImage value="#{bean.image}"> <f:param name="filename" value="filename.ext" /></p:graphicImage>
Note that the example #{bean}
is @ApplicationScoped
as it basically represents a stateless service. You can also make it @RequestScoped
, but then the bean would be recreated on every single request, for nothing. You cannot make it @ViewScoped
, because at the moment the browser needs to download the image, the server doesn't create a JSF page. You can make it @SessionScoped
, but then it's saved in memory, for nothing.
请注意,示例#{bean}是@ApplicationScoped,因为它基本上代表无状态服务。您也可以将其设为@RequestScoped,但是随后会在每个请求上重新创建bean。你无法使它成为@ViewScoped,因为目前浏览器需要下载图像,服务器不会创建一个JSF页面。你可以将其设为@SessionScoped,但它会保存在内存中,什么也不保存。
See also:
- Recommended way to save uploaded files in a servlet application
- Simplest way to serve static data from outside the application server in a Java web application
- Abstract template for a static resource servlet (supporting HTTP caching)
- Show image as byte[] from database as graphic image in JSF page
- Display dynamic image from database with p:graphicImage and StreamedContent
- How to choose the right bean scope?
建议在servlet应用程序中保存上载文件的方法
在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法
静态资源servlet的抽象模板(支持HTTP缓存)
在JSF页面中将图像作为byte []显示为图形图像
使用p:graphicImage和StreamedContent从数据库显示动态图像
如何选择合适的bean范围?
#2
In order to achieve what you need using <h:graphicImage>
or <img>
tags, you require to create a Tomcat v7 alias in order to map the external path to your web app's context.
为了使用
To do so, you will need to specify your web app's context. The easiest would be to define a META-INF/context.xml file with the following content:
为此,您需要指定Web应用程序的上下文。最简单的方法是使用以下内容定义META-INF / context.xml文件:
<Context path="/myapp" aliases="/images=/path/to/external/images"></Context>
Then after restarting your Tomcat server, you can access your images files using <h:graphicImage
> or <img>
tags as following:
然后在重新启动Tomcat服务器后,您可以使用
<h:graphicImage value="/images/my-image.png">
or
<img src="/myapp/images/my-image.png">
*Note the context path is necessary for the tag but not for the
*请注意,上下文路径是标记所必需的,但不是
Another possible approach if you don't require the images to be available through HTTP GET method, could be to use Primefaces <p:fileDownload>
tag (using commandLink or commandButton tags - HTTP POST method).
如果您不要求图像通过HTTP GET方法可用,另一种可能的方法是使用Primefaces
In your Facelet:
在你的Facelet中:
<h:form> <h:commandLink id="downloadLink" value="Download"> <p:fileDownload value="#{fileDownloader.getStream(file.path)}" /> </h:commandLink></h:form
In your bean:
在你的bean中:
@ManagedBean@ApplicationScopepublic 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; } }}
#3
In PrimeFaces you can implement your bean in this way:
在PrimeFaces中,您可以通过以下方式实现bean:
private StreamedContent image;public void setImage(StreamedContent image) { this.image = image;}public StreamedContent getImage() throws Exception { return image;}public void prepImage() throws Exception {File file = new File("/path/to/your/image.png");InputStream input = new FileInputStream(file);ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();setImage(new DefaultStreamedContent(input,externalContext.getMimeType(file.getName()), file.getName()));}
In your HTML Facelet:
在您的HTML Facelet中:
<body onload="#{yourBean.prepImage()}"></body> <p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" ></p:graphicImage>
I suggest to set the attribute cache="false" in the graphicImage component.
我建议在graphicImage组件中设置属性cache =“false”。
#4
In JSP
<img src="data:image/jpeg;base64,<%= new String(Base64.encode(Files.readAllBytes(Paths.get("C:\\temp\\A.jpg"))))%>"/>
Packages are com.sun.jersey.core.util.Base64
, java.nio.file.Paths
and java.nio.file.Files
.
包是com.sun.jersey.core.util.Base64,java.nio.file.Paths和java.nio.file.Files。