使用 <h:graphicImage> 从 webapps/webcontext/deploy 文件夹之外加载图像或 <img>标签 [英] Load images from outside of webapps / webcontext / deploy folder using &lt;h:graphicImage&gt; or &lt;img&gt; tag

查看:21
本文介绍了使用 <h:graphicImage> 从 webapps/webcontext/deploy 文件夹之外加载图像或 <img>标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

解决方案

就这一点而言,它必须可以通过公共 URL 访问.因此, 最终必须引用一个 http:// URI,而不是类似 file:// URI 之类的东西.最终,HTML 源代码在最终用户的机器上执行,图像在解析 HTML 源代码期间由网络浏览器单独下载.当 webbrowser 遇到 file:// URI,例如 C:path oimage.png 时,它会在最终用户自己的本地磁盘文件系统中查找图像而不是网络服务器的图像.如果网络浏览器在与网络服务器物理不同的机器上运行,这显然是行不通的.

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

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


  2. 或者,向服务器添加一个新的 webapp 上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置.如何做到这一点取决于所使用的容器.以下示例假设图像位于 /path/to/images 并且您希望通过 因此可以在纯 HTML 中引用如下

    <img src="#{request.contextPath}/images/filename.ext"/>

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

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

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

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

    <f:param name="filename" value="filename.ext"/></p:graphicImage>

    请注意,示例 #{bean}@ApplicationScoped,因为它基本上代表无状态服务.您也可以将其设为 @RequestScoped,但随后会在每个请求上重新创建 bean,而不会白费力气.你不能让它@ViewScoped,因为此时浏览器需要下载图像,服务器并没有创建一个JSF页面.你可以让它@SessionScoped,但它会被保存在内存中,什么都没有.

    另见:

    I need to display images which reside outside of deploy folder in web application using JSF <h:graphicimage> tag or HTML <img> tag. How can I achieve that?

    解决方案

    To the point, it has to be accessible by a public URL. Thus, the <img src> must ultimately refer a http:// URI, not something like a file:// URI or so. Ultimately, the HTML source is executed at enduser's machine and images are downloaded individually by the webbrowser during parsing the HTML source. When the webbrowser encounters a file:// URI such as C:path oimage.png, then it will look in enduser's own local disk file system for the image instead of the webserver's one. This is obviously not going to work if the webbrowser runs at a physically different machine than the webserver.

    There are several ways to achieve this:

    1. 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.


    2. 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" />
      


    3. 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.


    4. 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));
          }
      }
      


    5. 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)));
              }
          }
      }
      


    For the first way and the Tomcat and WildFly approaches in second way, the images will be available by http://example.com/images/filename.ext and thus referencable in plain HTML as follows

    <img src="/images/filename.ext" />
    

    For the GlassFish approach in second way and the third way, the images will be available by http://example.com/context/images/filename.ext and thus referencable in plain HTML as follows

    <img src="#{request.contextPath}/images/filename.ext" />
    

    or in JSF as follows (context path is automatically prepended)

    <h:graphicImage value="/images/filename.ext" />
    

    For the OmniFaces approach in fourth way, reference it as follows

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

    For the PrimeFaces approach in fifth way, reference it as follows:

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

    Note that the example #{bean} is @ApplicationScoped as it basically represents a stateless service. You can also make it @RequestScoped, but then the bean would be recreated on every single request, for nothing. You cannot make it @ViewScoped, because at the moment the browser needs to download the image, the server doesn't create a JSF page. You can make it @SessionScoped, but then it's saved in memory, for nothing.

    See also:

    这篇关于使用 <h:graphicImage> 从 webapps/webcontext/deploy 文件夹之外加载图像或 <img>标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆