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

时间:2010-12-28 05:43:29

标签: image jsf jsf-2 graphicimage

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

4 个答案:

答案 0 :(得分:72)

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

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

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


  2. 或者,向服务器添加一个新的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>

  3. 或者,创建一个<file name="images-content" path="/path/to/images" /> ,将图像从磁盘流式传输到响应:

    Servlet

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


  4. 或者,使用支持返回@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

  5. 或者,使用支持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

  6. 对于第一种方式,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.Base64java.nio.file.Pathsjava.nio.file.Files