<h:graphicimage>
标签或 HTML 的 <img>
标签来显示位于部署文件夹外的图像。我该如何实现?<h:graphicimage>
标签或 HTML 的 <img>
标签来显示位于部署文件夹外的图像。我该如何实现?<img src>
最终必须引用 http://
URI,而不是像 file://
URI 这样的东西。最终,HTML源代码在最终用户的计算机上执行,Web浏览器在解析HTML源代码期间单独下载图像。当Web浏览器遇到像 C:\path\to\image.png
这样的 file://
URI 时,它将在最终用户自己的本地磁盘文件系统中查找图像,而不是在Web服务器中查找。如果Web浏览器运行在与Web服务器物理上不同的计算机上,则显然无法正常工作。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.
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.
In case of Tomcat, add the following new entry to Tomcat's /conf/server.xml
inside <Host>
:
<Context docBase="/path/to/images" path="/images" />
In case of GlassFish, add the following entry to /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
...
<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:
@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.
Or, use OmniFaces <o:graphicImage>
which supports a bean property returning byte[]
or InputStream
:
@Named
@ApplicationScoped
public 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-specific StreamedContent
.
@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)));
}
}
}
对于第一种方法和第二种方法中的Tomcat和WildFly方法,图像将通过http://example.com/images/filename.ext可用,并且可以在普通HTML中引用,如下所示
<img src="/images/filename.ext" />
对于第二种和第三种方式中的GlassFish方法,图像将通过http://example.com/context/images/filename.ext可用,并且可以在普通HTML中引用,如下所示
<img src="#{request.contextPath}/images/filename.ext" />
或者在JSF中按照以下方式进行(上下文路径会自动添加)
<h:graphicImage value="/images/filename.ext" />
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
对于第五种方法中的PrimeFaces方法,请按以下方式引用:
<p:graphicImage value="#{bean.image}">
<f:param name="filename" value="filename.ext" />
</p:graphicImage>
#{bean}
是@ApplicationScoped
,因为它基本上代表了一个无状态服务。您也可以将其设置为@RequestScoped
,但那么该bean将在每个请求中重新创建,没有任何意义。您不能将其设置为@ViewScoped
,因为在浏览器需要下载图像的时候,服务器不会创建JSF页面。您可以将其设置为@SessionScoped
,但那么它将保存在内存中,没有任何意义。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()));
}
<body onload="#{yourBean.prepImage()}"></body>
<p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" >
</p:graphicImage>
<h:graphicImage>
或 <img>
标签实现您需要的功能,您需要创建一个 Tomcat v7 别名,将外部路径映射到您的 Web 应用程序上下文中。<Context path="/myapp" aliases="/images=/path/to/external/images">
</Context>
在重新启动Tomcat服务器后,您可以使用以下<h:graphicImage>
或<img>
标签访问您的图像文件:
<h:graphicImage value="/images/my-image.png">
或者
<img src="/myapp/images/my-image.png">
*注意,对于 <img>
标签来说,上下文路径是必须的,但对于
如果您不需要通过HTTP GET方法获取图像,则另一个可能的方法是使用Primefaces的<p:fileDownload>
标签(使用commandLink或commandButton标签 - HTTP POST方法)。
在您的Facelet中:
<h:form>
<h:commandLink id="downloadLink" value="Download">
<p:fileDownload value="#{fileDownloader.getStream(file.path)}" />
</h:commandLink>
</h:form
@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;
}
}
}
在JSP中
<img src="data:image/jpeg;base64,
<%= new String(Base64.encode(Files.readAllBytes(Paths.get("C:\\temp\\A.jpg"))))%>"/>
这些包是 com.sun.jersey.core.util.Base64
, java.nio.file.Paths
和 java.nio.file.Files
。
sun-web.xml
创建虚拟目录。http://www.marceble.com/2009/07/virtual-directories-in-glassfish/ - BalusC