这里存在一个重大误解。JSF基本上是一个HTML代码生成器。在HTML中,图像不会内联在HTML输出中。相反,它们应该由
<img>
元素表示,其中包含(相对)URL在
src
属性中,浏览器必须在解析获得的HTML输出时单独下载它们。查看生成的HTML输出,JSF
<h:graphicImage>
组件生成一个HTML
<img>
元素,必须具有指向有效URL的
src
属性。
<h:graphicImage value>
必须表示有效的URL。但是,如果您将图像存储在数据库中而不是公共Web内容中,则应基本上创建一个独立的
servlet,该servlet根据某些唯一请求参数或URL路径从DB中读取各个图像并将其写入响应正文。
因此,假设您从现在开始按以下方式呈现图像URL,
<h:graphicImage value="/userProfileImageServlet?id=#{userProfile.id}" />
接下来这个启动示例(忽略了像空值检查等)的servlet应该做:
@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);
}
}
}
它还通过设置
dataURI="true"
来透明地
支持日期URI方案:
<o:graphicImage value="#{userProfileImageBean.getBytes(userProfile.id)}" dataURI="true" />
另请参阅: