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

Mun*_*ian 42 jsf image jsf-2 graphicimage

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

Bal*_*usC 74

到目前为止,它必须可以通过公共URL访问.因此,<img src>必须最终引用http://URI,而不是file://URI 等.最终,HTML源在最终用户的机器上执行,并且在解析HTML源期间,webbrowser单独下载图像.当webbrowser遇到file://诸如的URI C:\path\to\image.png之后,它将在终端用户自己的本地磁盘文件系统中查找图像而不是web服务器的图像.如果webbrowser在与Web服务器不同的机器上运行,这显然不会起作用.

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

  1. 如果你完全控制images文件夹,那么只需删除包含所有图像的文件夹,例如/images直接放在servletcontainer的deploy文件夹中,例如/webappsTomcat的/domains/domain1/applications文件夹和GlassFish的文件夹.无需进一步配置.


  2. 或者,向服务器添加一个新的webapp上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置.怎么做取决于使用的容器.以下示例假定图像位于/path/to/images您希望通过http://.../images访问它们.

    在Tomcat的情况下,将以下新条目添加到Tomcat的/conf/server.xml内部<Host>:

    <Context docBase="/path/to/images" path="/images" />
    
    Run Code Online (Sandbox Code Playgroud)

    如果是GlassFish,请将以下条目添加到/WEB-INF/glassfish-web.xml:

    <property name="alternatedocroot_1" value="from=/images/* dir=/path/to" />
    
    Run Code Online (Sandbox Code Playgroud)

    在WildFly的情况下,里面添加以下条目<host name="default-host">/standalone/configuration/standalone.xml...

    <location name="/images" handler="images-content" />
    
    Run Code Online (Sandbox Code Playgroud)

    ...并进一步向下<handlers>的非常相同的条目<subsystem>如上<location>:

    <file name="images-content" path="/path/to/images" />
    
    Run Code Online (Sandbox Code Playgroud)
  3. 或者,创建一个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());
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    如果您碰巧使用OmniFaces,那么它FileServlet可能很有用,因为它还会考虑头部,缓存和范围请求.


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

    @Named
    @ApplicationScoped
    public class Bean {
    
        public InputStream getImage(String filename) {
            return new FileInputStream(new File("/path/to/images", filename));
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. 或者,使用PrimeFaces<p:graphicImage>支持bean方法返回PrimeFaces特异性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)));
            }
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)

对于第一种方式,Tomcat和WildFly以第二种方式接近,图像将可以通过http://example.com/images/filename.ext获得,因此可以在纯HTML中按照以下方式引用

<img src="/images/filename.ext" />
Run Code Online (Sandbox Code Playgroud)

对于第二种方式和第三种方式的GlassFish方法,图像将通过http://example.com/context/images/filename.ext提供,因此可以在纯HTML中按照以下方式进行引用:

<img src="#{request.contextPath}/images/filename.ext" />
Run Code Online (Sandbox Code Playgroud)

或者在JSF中如下(上下文路径自动添加)

<h:graphicImage value="/images/filename.ext" />
Run Code Online (Sandbox Code Playgroud)

对于第四种方式的OmniFaces方法,请参考如下

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

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

<p:graphicImage value="#{bean.image}">
    <f:param name="filename" value="filename.ext" />
</p:graphicImage>
Run Code Online (Sandbox Code Playgroud)

请注意,该示例#{bean}@ApplicationScoped因为它基本上代表无状态服务.您也可以创建它@RequestScoped,但是随后会在每个请求上重新创建bean.你无法做到@ViewScoped,因为目前浏览器需要下载图像,服务器不会创建JSF页面.你可以做到@SessionScoped,但它会被保存在内存中,什么都不做.

也可以看看:


归档时间:

查看次数:

65275 次

最近记录:

6 年,9 月 前