ここに大きな誤解があります。JSF は基本的に HTML コード プロデューサーです。HTML では、イメージは HTML 出力でインライン化されません。代わりに、取得した HTML 出力の解析中にブラウザーが個別にダウンロードする必要が<img>
ある属性の (相対) URL を持つ要素によって表されることになっています。src
生成された HTML 出力を見てください。JSFコンポーネントは、有効な URL を指す属性を持つ必要がある<h:graphicImage>
HTML 要素を生成します。<img>
src
は<h:graphicImage value>
有効な URL を表す必要があります。ただし、パブリック Web コンテンツではなく DB に画像を保存した場合は、基本的に、一意の要求パラメーターまたは URL パスに基づいて DB から個々の画像を読み取り、それを応答本文に書き込むスタンドアロンサーブレットを作成する必要があります。 .
したがって、これから画像の URL を次のようにレンダリングすると仮定すると、
<h:graphicImage value="/userProfileImageServlet?id=#{userProfile.id}" />
次に、サーブレットの次のキックオフ例 (nullchecks などの簡単なチェックは省略) を実行する必要があります。
@WebServlet("/userProfileImageServlet")
public class UserProfileImageServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Long userProfileId = Long.valueOf(request.getParameter("id"));
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image, imageFileName, LENGTH(image) AS imageContentLength FROM userProfile WHERE id=?");
) {
statement.setLong(1, userProfileId);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
response.setContentType(getServletContext().getMimeType(resultSet.getString("imageFileName")));
response.setContentLength(resultSet.getInt("imageContentLength"));
response.setHeader("Content-Disposition", "inline;filename=\"" + resultSet.getString("imageFileName") + "\"");
try (
ReadableByteChannel input = Channels.newChannel(resultSet.getBinaryStream("image"));
WritableByteChannel output = Channels.newChannel(externalContext.getResponseOutputStream());
) {
for (ByteBuffer buffer = ByteBuffer.allocateDirect(10240); input.read(buffer) != -1; buffer.clear()) {
output.write((ByteBuffer) buffer.flip());
}
}
}
} else {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
} catch (SQLException e) {
throw new ServletException("Something failed at SQL/DB level.", e);
}
}
}
JSF 2.2 + CDI 環境でJSF ユーティリティ ライブラリOmniFaces<o:graphicImage>
を使用している場合は、代わりに、より直感的に使用できるものを使用できます。
<o:graphicImage value="#{userProfileImageBean.getBytes(userProfile.id)}" />
@Named
@ApplicationScoped
public class UserProfileImageBean {
public byte[] getBytes(Long userProfileId) {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement("SELECT image FROM userProfile WHERE id=?");
) {
statement.setLong(1, userProfileId);
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
return resultSet.getBytes("image");
}
} else {
return null;
}
} catch (SQLException e) {
throw new FacesException("Something failed at SQL/DB level.", e);
}
}
}
また、次のように設定するだけで、日付 URI スキームを透過的にサポートしdataURI="true"
ます。
<o:graphicImage value="#{userProfileImageBean.getBytes(userProfile.id)}" dataURI="true" />
以下も参照してください。