5

ImageManagedBean にオブジェクトを取得しました。JSF ページでそれを取得するにはどうすればよいですか?

これは機能していないようです: <h:graphicImage value="#{userProfile.image}" />image はクラス userProfile のフィールド変数です。

イメージは、以下のように 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);
}

私が得たエラーは次のとおりjava.lang.ClassCastException - sun.awt.image.ToolkitImage cannot be cast to java.lang.Stringです。

4

2 に答える 2

7

ここに大きな誤解があります。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" />

以下も参照してください。

于 2013-02-25T19:29:42.297 に答える