0

com.I には、ユーザーが画像をアップロードする SWF アプリがあり、その画像は次のフロー状態で表示する必要があります。フローは、ユーザーが入力したすべてのデータを格納する会話スコープ Bean (実際には JPA エンティティ) を使用します。画像をアップロードして Bean に保存することはできますが、PrimeFaces の graphicImage facelet ではレンダリングされません。いくつかの調査を行ったところ、PF GI コンポーネントのレンダリング中に、セッションで評価される EL 式が格納され、その後の ResourceHandler への呼び出し (レンダリングされた HTML の IMG タグによって行われる) によって、同じ EL 式がフェッチされ、実際に評価されるようです。問題は、 ResourceHandler がすべてのデータを保存するフロー変数にアクセスできないため、画像をレンダリングできないことです。

PF GI コンポーネントを拡張して、EL 式の代わりにセッションで実際の画像を保存しましたが、パフォーマンスに明らかな影響があります。バイナリ データをセッションに保存することはお勧めできません。また、セキュリティ上の理由から、すべてのデータをセッションではなくフロー/会話スコープに保持したいと思います。

PF GI コンポーネントがフロー変数にアクセスできるようにするクリーンな方法はありますか?

以下の私のコードのスニペット

流れ:

<on-start>
    <evaluate expression="new my.models.Customers()" result="conversationScope.customer"></evaluate>
</on-start>

<view-state id="scanImage" view="s1-scan.xhtml" model="customer" >
    <secured attributes="ROLE_WEB" />
    <transition on="submit" to="verifyImage"></transition>
    <transition on="cancel" to="canceled"></transition>
</view-state>

<view-state id="verifyImage" view="s2-verifyscan.xhtml" model="customer">
    <secured attributes="ROLE_WEB" />
    <transition on="submit" to="enterDetails"></transition>
    <transition on="back" to="scanImage"></transition>
    <transition on="cancel" to="canceled"></transition>
</view-state>

画像のレンダリング:

<p:graphicImage value="#{customer.getImageSC()}"></p:graphicImage>

パッチを適用した GraphicImageRenderer.getImageSrc()

protected String getImageSrc(FacesContext context, GraphicImage image) {
    String src = null;
String name = image.getName();

if(name != null) {
    String libName = image.getLibrary();
    ResourceHandler handler = context.getApplication().getResourceHandler();
    Resource res = handler.createResource(name, libName);

    if(res == null) {
        return "RES_NOT_FOUND";
    } 
    else {
        String requestPath = res.getRequestPath();

        return context.getExternalContext().encodeResourceURL(requestPath);
    }
}
else {
    Object value = image.getValue();

    if(value == null) {
        return "";
    }
    else  if(value instanceof String) {
        src = getResourceURL(context, (String) value);
    }
    else if(value instanceof StreamedContent) {
        StreamedContent streamedContent = (StreamedContent) value;
        Resource resource = context.getApplication().getResourceHandler().createResource("dynamiccontent", "primefaces", streamedContent.getContentType());
        String resourcePath = resource.getRequestPath();
        String rid = createUniqueContentId(context);
        StringBuilder builder = new StringBuilder(resourcePath);

        builder.append("&").append(Constants.DYNAMIC_CONTENT_PARAM).append("=").append(rid);

        for(UIComponent kid : image.getChildren()) {
            if(kid instanceof UIParameter) {
                UIParameter param = (UIParameter) kid;

                builder.append("&").append(param.getName()).append("=").append(param.getValue());
            }
        }

        src = builder.toString();

        context.getExternalContext().getSessionMap().put(rid, value);
        // context.getExternalContext().getSessionMap().put(rid, image.getValueExpression("value").getExpressionString());
    }

    if(!image.isCache()) {
        src += src.contains("?") ? "&" : "?";
        src += "primefaces_image=" + UUID.randomUUID().toString();
    }

    src = context.getExternalContext().encodeResourceURL(src);
}

    return src;
}

ハンドラ:

public void handleResourceRequest(FacesContext context) throws IOException {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
String library = params.get("ln");
String dynamicContentId = params.get(Constants.DYNAMIC_CONTENT_PARAM);

if(dynamicContentId != null && library != null && library.equals("primefaces")) {
    Map<String,Object> session = context.getExternalContext().getSessionMap();
    StreamedContent streamedContent = null;

    try {

        Object dynamicContentEL = (Object) session.get(dynamicContentId);

        //String dynamicContentEL = (String) session.get(dynamicContentId);
        //ELContext eLContext = context.getELContext();
        //ValueExpression ve = context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(), dynamicContentEL, StreamedContent.class);
        //streamedContent = (StreamedContent) ve.getValue(eLContext);

        streamedContent = (StreamedContent) dynamicContentEL;

        ExternalContext externalContext = context.getExternalContext();
        externalContext.setResponseStatus(200);
        externalContext.setResponseContentType(streamedContent.getContentType());

        byte[] buffer = new byte[2048];

        int length;
        InputStream inputStream = streamedContent.getStream();
        while ((length = (inputStream.read(buffer))) >= 0) {
            externalContext.getResponseOutputStream().write(buffer, 0, length);
        }

        externalContext.responseFlushBuffer();
        context.responseComplete();

    } catch(Exception e) {
        logger.log(Level.SEVERE, "Error in streaming dynamic resource. {0}", new Object[]{e.getMessage()});
    }
    finally {
        //cleanup
        session.remove(dynamicContentId);

        if(streamedContent != null) {
            streamedContent.getStream().close();
        }
    }
}
else {
   super.handleResourceRequest(context); 
}

}

顔構成:

   <application>
        <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
        <resource-handler>com.my.PrimeResourceHandler</resource-handler>
    </application>

<render-kit>    
    <renderer>
         <component-family>org.primefaces.component</component-family>
         <renderer-type>org.primefaces.component.graphicimage.GraphicImageRenderer</renderer-type>
         <renderer-class>com.my.GraphicImageRenderer</renderer-class>
    </renderer>
</render-kit>

Webflow コンテキストを EL と一緒に Session オブジェクトに保存し、EL を評価するときにそのコンテキストを使用するようにリソース ハンドラーを作成することが可能であると思われます...

4

1 に答える 1

0

primefaces コード (つまり、GraphicImageRenderer クラスと PrimeResourceHandler クラス) を変更したか、またはそれらを拡張しましたか? それらを拡張した場合、コードは拡張されたクラスを使用/呼び出すことをどのように知っていましたか?

私はリクエストスコープを使用し、すべての画像をWEB-INFフォルダーに保存し、以下を使用してそれらを取得しています:

<p:graphicImage value="/images/{springBean.imageFileName}"> 

今後のバージョンで修正される可能性があるため、primefaces コードには変更を加えていません。ただし、フロースコープを使用したいのですが、以下のように Bean を使用してそれらを取得したいと考えています。

<p:graphicImage value="#{springBean.imageFile}">

また、webapproot にないハード ドライブの場所に画像を保存しようとしたため、graphicImage を表示できません。/images/* へのすべてのリクエストを、websphere で以下のようにコントローラー/マネージド Bean を使用せずにローカル フォルダーにマップできたらいいのにと思いませんか?

サーバー上の画像を Java Web アプリケーションで保存および取得する方法

于 2012-11-15T19:24:09.457 に答える