使用 <h:graphicImage> 或 <img> 标签从 webapps / webcontext / deploy 文件夹外部加载图像
Posted
技术标签:
【中文标题】使用 <h:graphicImage> 或 <img> 标签从 webapps / webcontext / deploy 文件夹外部加载图像【英文标题】:Load images from outside of webapps / webcontext / deploy folder using <h:graphicImage> or <img> tag 【发布时间】:2011-05-31 10:41:21 【问题描述】:我需要使用 JSF <h:graphicimage>
标记或 html <img>
标记显示驻留在 Web 应用程序中部署文件夹之外的图像。我怎样才能做到这一点?
【问题讨论】:
【参考方案1】:重要的是,它必须可以通过公共 URL 访问。因此,<img src>
最终必须引用 http://
URI,而不是 file://
URI 左右。最终,HTML 源代码在最终用户的机器上执行,并且图像在解析 HTML 源代码期间由网络浏览器单独下载。当网络浏览器遇到file://
URI 例如C:\path\to\image.png
时,它将在最终用户自己的本地磁盘文件系统中查找图像,而不是在网络服务器的文件系统中查找。如果网络浏览器在物理上与网络服务器不同的机器上运行,这显然是行不通的。
有几种方法可以实现这一点:
如果您可以完全控制图像文件夹,则只需删除包含所有图像的文件夹,例如/images
直接在 servletcontainer 的 deploy 文件夹中,例如 Tomcat 的 /webapps
文件夹和 GlassFish 的 /domains/domain1/applications
文件夹。无需进一步配置。
或者,向服务器添加一个新的 webapp 上下文,该上下文指向包含这些图像的文件夹的绝对磁盘文件系统位置。如何做到这一点取决于使用的容器。下面的示例假设图像位于/path/to/images
,并且您希望通过http://.../images 访问它们。
如果是 Tomcat,将以下新条目添加到 Tomcat 的 /conf/server.xml
内的 <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">
of /standalone/configuration/standalone.xml
中添加以下条目 ...
<location name="/images" handler="images-content" />
...在<handlers>
的下方,与上面<location>
完全相同的<subsystem>
条目:
<file name="images-content" path="/path/to/images" />
或者,创建一个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());
如果您碰巧使用 OmniFaces,那么 FileServlet
可能会很有用,因为它还考虑了头部、缓存和范围请求。
或者,使用支持返回byte[]
或InputStream
的bean 属性的OmniFaces <o:graphicImage>
:
@Named
@ApplicationScoped
public class Bean
public InputStream getImage(String filename)
return new FileInputStream(new File("/path/to/images", filename));
或者,使用 PrimeFaces <p:graphicImage>
,它支持返回 PrimeFaces 特定 StreamedContent
的 bean 方法。
@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)));
对于第一种方式和第二种方式的 Tomcat 和 WildFly 方法,图像将由 http://example.com/images/filename.ext 提供,因此可以在纯 HTML 中引用,如下所示
<img src="/images/filename.ext" />
对于第二种和第三种方式的 GlassFish 方法,图像将由http://example.com/context/images/filename.ext 提供,因此可以在纯 HTML 中引用,如下所示
<img src="#request.contextPath/images/filename.ext" />
或在JSF中如下(上下文路径自动添加)
<h:graphicImage value="/images/filename.ext" />
对于第四种方式的OmniFaces方法,参考如下
<o:graphicImage value="#bean.getImage('filename.ext')" />
对于第五种方式的PrimeFaces方法,参考如下:
<p:graphicImage value="#bean.image">
<f:param name="filename" value="filename.ext" />
</p:graphicImage>
请注意,示例 #bean
是 @ApplicationScoped
,因为它基本上代表无状态服务。您也可以将其设为@RequestScoped
,但随后将在每个请求上重新创建 bean,而一无所获。你不能让它@ViewScoped
,因为在浏览器需要下载图像的那一刻,服务器并没有创建一个JSF页面。你可以把它设为@SessionScoped
,但它会被保存在内存中,一无所获。
另见:
Recommended way to save uploaded files in a servlet application Simplest way to serve static data from outside the application server in a Java web application Abstract template for a static resource servlet(支持 HTTP 缓存) Show image as byte[] from database as graphic image in JSF page Display dynamic image from database with p:graphicImage and StreamedContent How to choose the right bean scope?【讨论】:
嗨 BalusC,感谢您的快速回复。如果我在 linux 中使用它,我的图像的绝对路径是 /home/muneeswaran/apache-tomcat-6.0.29/headers/Aboutus/images/ ss.jpg.SO 我可以在 server.xml 中将上下文存储为sun-web.xml
中创建一个虚拟目录。 marceble.com/2009/07/virtual-directories-in-glassfish【参考方案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
>或者<img>
标签访问你的图片文件,如下:
<h:graphicImage value="/images/my-image.png">
或
<img src="/myapp/images/my-image.png">
*注意上下文路径对于标签是必需的,而不是对于
如果您不要求图像通过 HTTP GET 方法可用,另一种可能的方法是使用 Primefaces <p:fileDownload>
标签(使用 commandLink 或 commandButton标签 - 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;
【讨论】:
【参考方案3】:在 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>
我建议在graphicImage组件中设置属性cache="false"。
【讨论】:
【参考方案4】:在 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
。
【讨论】:
我们不会在 JSF 而不是 JSP 中 这在 JSF 中怎么可能?以上是关于使用 <h:graphicImage> 或 <img> 标签从 webapps / webcontext / deploy 文件夹外部加载图像的主要内容,如果未能解决你的问题,请参考以下文章
无法使用 h:graphicImage JSF 2.0 显示图像
在不使用过滤器和包装器的情况下删除 URL 中的 JSESSIONID
<q>、<blockquote> 和 <cite> 的有效使用
何时使用 Mono<List<Object>> 以及何时使用 Flux<Object> 用于 RestController 方法