我需要使用JSF <h:graphicimage>
标记或HTML <img>
标记在Web应用程序中显示位于deploy文件夹之外的图像。我怎样才能做到这一点?
答案 0 :(得分:72)
到目前为止,它必须可以通过公共URL访问。因此,<img src>
最终必须引用http://
URI,而不是file://
URI左右。最终,HTML源在最终用户的机器上执行,并且在解析HTML源期间,webbrowser单独下载图像。当webbrowser遇到file://
URI(例如C:\path\to\image.png
)时,它将在终端用户自己的本地磁盘文件系统中查找图像,而不是网络服务器的图像。如果webbrowser在与Web服务器不同的机器上运行,这显然不会起作用。
有几种方法可以实现这一目标:
如果您完全控制图像文件夹,则只需删除包含所有图像的文件夹,例如/images
直接在servletcontainer的deploy文件夹中,例如Tomcat的/webapps
文件夹和GlassFish的/domains/domain1/applications
文件夹。无需进一步配置。
或者,向服务器添加一个新的webapp上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置。怎么做取决于使用的容器。以下示例假定图片位于/path/to/images
,并且您希望通过http://.../images访问它们。
如果是Tomcat,请将以下新条目添加到/conf/server.xml
内的Tomcat <Host>
:
<Context docBase="/path/to/images" path="/images" />
如果是GlassFish,请将以下条目添加到/WEB-INF/glassfish-web.xml
:
<property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
如果是WildFly,请在<host name="default-host">
的{{1}}内添加以下条目...
/standalone/configuration/standalone.xml
...并进一步向下<location name="/images" handler="images-content" />
与<handlers>
相同的<subsystem>
条目:
<location>
或者,创建一个<file name="images-content" path="/path/to/images" />
,将图像从磁盘流式传输到响应:
Servlet
如果您碰巧使用OmniFaces,那么FileServlet
可能会有用,因为它还会考虑头部,缓存和范围请求。
或者,使用支持返回@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());
}
}
或byte[]
的bean属性的OmniFaces <o:graphicImage>
:
InputStream
或者,使用支持bean方法的PrimeFaces <p:graphicImage>
返回特定于PrimeFaces的@Named
@ApplicationScoped
public class Bean {
public InputStream getImage(String filename) {
return new FileInputStream(new File("/path/to/images", filename));
}
}
。
StreamedContent
对于第一种方式,Tomcat和WildFly以第二种方式接近,图像将由http://example.com/images/filename.ext提供,因此可以在纯HTML中引用,如下所示
@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)));
}
}
}
对于第二种方式和第三种方式的GlassFish方法,图像将由http://example.com/context/images/filename.ext提供,因此可以用纯HTML进行引用,如下所示
<img src="/images/filename.ext" />
或在JSF中如下(上下文路径自动添加)
<img src="#{request.contextPath}/images/filename.ext" />
对于第四种方式的OmniFaces方法,请参考如下
<h:graphicImage value="/images/filename.ext" />
对于第五种方式的PrimeFaces方法,请参考如下:
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
请注意,示例<p:graphicImage value="#{bean.image}">
<f:param name="filename" value="filename.ext" />
</p:graphicImage>
为#{bean}
,因为它基本上代表无状态服务。您也可以将其设为@ApplicationScoped
,但随后会在每个请求上重新创建bean,无需任何操作。你不能使它@RequestScoped
,因为在浏览器需要下载图像的那一刻,服务器不会创建一个JSF页面。你可以把它@ViewScoped
,然后把它保存在内存中,什么也不保存。
答案 1 :(得分:2)
为了使用<h:graphicImage>
或<img>
标记实现您的需求,您需要创建一个Tomcat v7别名,以便将外部路径映射到您的Web应用程序的上下文。
为此,您需要specify your web app's context。最简单的方法是使用以下内容定义META-INF / context.xml文件:
<Context path="/myapp" aliases="/images=/path/to/external/images">
</Context>
然后在重新启动Tomcat服务器后,您可以使用<h:graphicImage
&gt;访问您的图像文件。或<img>
标记如下:
<h:graphicImage value="/images/my-image.png">
或
<img src="/myapp/images/my-image.png">
*请注意,上下文路径对于标记是必需的,但对于
则不是如果您不要求图像通过HTTP GET方法可用,另一种可能的方法是使用Primefaces <p:fileDownload>
标记(使用 commandLink 或 commandButton tags - HTTP POST方法)。
在你的Facelet中:
<h:form>
<h:commandLink id="downloadLink" value="Download">
<p:fileDownload value="#{fileDownloader.getStream(file.path)}" />
</h:commandLink>
</h:form
在你的bean中:
@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;
}
}
}
答案 2 :(得分:0)
在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()));
}
在HTML Facelet中:
<body onload="#{yourBean.prepImage()}"></body>
<p:graphicImage value="#{youyBean.image}" style="width:100%;height:100%" cache="false" >
</p:graphicImage>
我建议设置属性cache =&#34; false&#34;在graphicImage组件中。
答案 3 :(得分:-1)
在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
。