JSFを使用して、Webアプリケーションのdeployフォルダーの外部にあるイメージを表示する必要があります<h:graphicimage>
タグまたはHTML <img>
タグ。どうすればそれを達成できますか?
要は、パブリックURLでアクセスできる必要があります。したがって、<img src>
は最終的にhttp://
URIなどではなく、file://
URIを参照する必要があります。最終的に、HTMLソースはエンドユーザーのマシンで実行され、画像はHTMLソースの解析中にWebブラウザーによって個別にダウンロードされます。 Webブラウザーがfile://
などのC:\path\to\image.png
URIを検出すると、Webサーバーの代わりにエンドユーザー自身のローカルディスクファイルシステムで画像を検索します。 WebブラウザがWebサーバーとは物理的に異なるマシンで実行されている場合、これは明らかに機能しません。
これを実現するには、いくつかの方法があります。
画像フォルダーを完全に制御できる場合は、すべての画像を含むフォルダーをドロップするだけです。 Tomcatの場合は/images
フォルダー、GlassFishの場合は/webapps
フォルダーなど、servletcontainerのdeployフォルダーに直接/domains/domain1/applications
。これ以上の構成は必要ありません。
または、新しい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">
の/standalone/configuration/standalone.xml
内に次のエントリを追加します...
<location name="/images" handler="images-content" />
...そして、上記とまったく同じ<handlers>
の<subsystem>
エントリのさらに下の<location>
:
<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
は、ヘッド、キャッシュ、および範囲のリクエストも考慮に入れるので便利です。
または、 OmniFaces <o:graphicImage>
を使用して、byte[]
またはInputStream
を返すBeanプロパティをサポートします。
@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が2番目の方法でアプローチする場合、イメージは http://example.com/images/filename.ext で利用できるため、次のようにプレーンHTMLで参照可能です。
<img src="/images/filename.ext" />
2番目と3番目の方法でのGlassFishアプローチの場合、イメージは http://example.com/context/images/filename.ext で利用できるため、プレーンHTMLで次のように参照できます。
<img src="#{request.contextPath}/images/filename.ext" />
またはJSFでは次のようになります(コンテキストパスは自動的に追加されます)
<h:graphicImage value="/images/filename.ext" />
4番目の方法でのOmniFacesアプローチについては、次のように参照してください。
<o:graphicImage value="#{bean.getImage('filename.ext')}" />
5番目の方法でのPrimeFacesアプローチについては、次のように参照してください。
<p:graphicImage value="#{bean.image}">
<f:param name="filename" value="filename.ext" />
</p:graphicImage>
サンプル#{bean}
は、基本的にステートレスサービスを表すため、@ApplicationScoped
であることに注意してください。 @RequestScoped
にすることもできますが、Beanはリクエストがないたびにすべてのリクエストで再作成されます。ブラウザが画像をダウンロードする必要がある時点で、サーバーはJSFページを作成しないため、@ViewScoped
にすることはできません。 @SessionScoped
にすることはできますが、その後はメモリに保存されます。
<h:graphicImage>
または<img>
タグを使用して必要なものを実現するには、外部パスをWebアプリのコンテキストにマップするためにTomcat v7エイリアスを作成する必要があります。
そのためには、 Webアプリのコンテキストを指定 にする必要があります。最も簡単な方法は、次の内容で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 method)。
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;
}
}
}
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"を設定することをお勧めします。