如何使用数据库中的图像内容填充h:graphicImage值?

Cac*_*ing 5 database jsf blob bytearray graphicimage

Image我的ManagedBean中有对象.如何在我的JSF页面中获取它?

这似乎不起作用: <h:graphicImage value="#{userProfile.image}" />其中image是类userProfile中的字段变量.

Image来自MySql,如下所示.

int len = rs.getInt("ImageLen");
if(len != 0){
    byte[] b = new byte[len];
    InputStream in = rs.getBinaryStream("Image");
    in.read(b);
    in.close();
    this.image = Toolkit.getDefaultToolkit().createImage(b);
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:java.lang.ClassCastException - sun.awt.image.ToolkitImage cannot be cast to java.lang.String.

Bal*_*usC 6

这里有一个重大的误解.JSF基本上是一个HTML代码生成器.在HTML中,HTML输出中没有内嵌图像.相反,它们应该由<img>属性中的(相对)URL元素表示,src浏览器在解析获得的HTML输出时必须单独下载该属性.查看生成的HTML输出,JSF <h:graphicImage>组件生成一个HTML <img>元素,该元素必须具有src指向有效URL 的属性.

<h:graphicImage value>必须代表一个合法的URL.但是,如果您已将图像存储在数据库而不是公共Web内容中,那么您应该基本创建一个独立的servlet,它根据一些唯一的请求参数或URL路径从数据库中读取单个映像,并将其写入响应正文.

因此,假设您从现在开始渲染图像URL,

<h:graphicImage value="/userProfileImageServlet?id=#{userProfile.id}" />
Run Code Online (Sandbox Code Playgroud)

然后servlet应该执行以下启动示例(省略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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

如果您碰巧在JSF 2.2 + CDI环境中使用JSF实用程序库OmniFaces,那么您可以使用它<o:graphicImage>来更直观地使用它.

<o:graphicImage value="#{userProfileImageBean.getBytes(userProfile.id)}" />
Run Code Online (Sandbox Code Playgroud)

@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);
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

它还通过设置透明地支持日期URI方案dataURI="true":

<o:graphicImage value="#{userProfileImageBean.getBytes(userProfile.id)}" dataURI="true" />
Run Code Online (Sandbox Code Playgroud)

也可以看看: