4

ファイルをダウンロードするための関数を呼び出す commandButton があります ( ... のような標準的なもの) InputStreamBufferedOutputStreamこれらはすべて正しく機能します。ファイルのダウンロードが完了しても、ページのコンテンツは更新されません。更新されたコンテンツを表示するには、更新を押す必要があります。助けてください。以下は私のコードの基本的な構造です

document: Managed Bean
getDrawings(): Drawing(エンティティクラス)のリストを返すメソッド
CheckedOutBy: Entityの属性Drawing

<p:dataTable id="drawing_table" value="#{document.drawings}" var="item" >                            
    <p:column>
        <f:facet name="header">
              <h:outputText value="CheckedOutBy"/>
        </f:facet>
        <h:outputText value="#{item.checkedOutBy}"/>
        ...
</p:dataTable>
<p:commandButton ajax="false" action="#{document.Download}" value="Download" />

マネージド Bean の内部

public void Download(){
    Drawing drawing = getCurrentDrawing();
    //Download drawing
    drawing.setCheckedOutBy("Some Text");
    sBean.merge(drawing);  //Update "Some Text" into CheckedOutBy field
}
4

4 に答える 4

4

基本的に、クライアントに2 つのリクエストを発行させたいと考えています。1 つはダウンロードを取得し、もう 1 つは新しいページを更新します。これらは、単一の HTTP 要求では実行できません。ダウンロードは同期的に行う必要があり、クライアント側からダウンロードの完了をフックする方法がないため、ダウンロードの完了時にコンポーネントを更新するためのクリーンな JSF/JS/Ajax の方法はありません。

PrimeFaces の助けを借りたあなたの最善の JSF 賭けは<p:poll>

<h:outputText id="checkedOutBy" value="#{item.checkedOutBy}"/>
...
<p:poll id="poll" interval="5" update="checkedOutBy" />

また<p:push>

<p:push onpublish="javaScriptFunctionWhichUpdatesCheckedOutBy" />  

ポーリングは簡単ですが、不要なオーバーヘッドが追加されることは想像に難くありません。同期ダウンロードの開始時に、標準の JSF/PrimeFaces コンポーネントを使用して開始することはできません。renderedただし、停止して属性のセルフチェックを実行させることができます。プッシュは技術的には最善の解決策ですが、始めるのはより困難です。PrimeFaces は、ユーザー ガイドの第 6 章でその使用方法をうまく説明しています。

于 2010-08-13T02:03:47.017 に答える
2

さて、私は上記の BalusC の回答/推奨事項に従うことにし、「後で」ここに立ち寄る可能性のある人々のために、ここでコードを共有することにしました。参考までに、私の環境の詳細は以下のとおりです。

TomEE 1.6.0 SNAPSHOT (Tomcat 7.0.39)、PrimeFaces 3.5 (PrimeFaces Push)、Atmosphere 1.0.13 スナップショット (1.0.12 が最新の安定バージョン)

まず、p:commandLink で p:fileDownload を使用しています。

<p:commandLink value="Download" ajax="false"
               actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}">
    <p:fileDownload value="#{driverWorksheet.file}"/>
</p:commandLink>

上記の xhtml があり、p:fileDownload では oncomplete="someJavaScript()" の実行が許可されていないため、PrimeFaces Push を使用してメッセージをクライアントにプッシュし、UI のブロックを解除するために必要な JavaScript をトリガーすることにしました。 commandLink をクリックしてファイルをダウンロードするたびにブロックされていました。何ヶ月もの間、これを解決する方法がわかりませんでした。

私はすでに PrimeFaces Push を使用しているため、クライアント側で以下を微調整する必要がありました。

.js ファイル; サーバーからクライアントにプッシュされたメッセージを処理するメソッドが含まれています

function handlePushedMessage(msg) {
    /* refer to primefaces.js, growl widget,
     * search for: show, renderMessage, e.detail
     * 
     * sample msg below:
     * 
     * {"data":{"summary":"","detail":"displayLoadingImage(false)","severity":"Info","rendered":false}}
     */
    if (msg.detail.indexOf("displayLoadingImage(false)") != -1) {
        displayLoadingImage(false);
    }
    else {
        msg.severity = 'info';
        growl.show([msg]);
    }
}

index.xhtml; p:socket コンポーネント (PrimeFaces Push) が含まれています。PrimeFaces Push の FacesMessage の例を実装している場合は、次のすべてをお勧めします。

<h:outputScript library="primefaces" name="push/push.js" target="head" />
<p:growl id="pushedNotifications" for="socketForNotifications"
         widgetVar="growl" globalOnly="false"
         life="30000" showDetail="true" showSummary="true" escape="false"/>
<p:socket id="socketForNotifications" onMessage="handlePushedMessage"
          widgetVar="socket"
          channel="/#{pf_usersController.userPushChannelId}" />

数か月前 (またはおそらく 1 年ほど前)、p:fileDownload をラップする commandLink に次を追加する必要があることがわかりました。これにより、サーバー上のファイル/ストリームが更新され、ファイルを何度でもクリックできるようになります。キーボードの F5/refresh キー (またはモバイル デバイスの同様のキー) を使用してページを更新せずに、ファイルが必要であり、何度もダウンロードします。

actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}"

その Bean メソッドは、エンドユーザーが commandLink をクリックしてファイルをダウンロードするたびに参照されるため、サーバーからクライアントにメッセージを「プッシュ」し、クライアントで JavaScript をトリガーし、UI のブロックを解除するのに最適な場所でした。

以下は、仕事を成し遂げる私のアプリの Bean メソッドです。:)

pf_ordersController.refreshDriverWorksheetsToDownload()

public String refreshDriverWorksheetsToDownload() {
    String returnValue = prepareDriverWorksheetPrompt("download", false);
    usersController.pushNotificationToUser("displayLoadingImage(false)");
    return returnValue;
}

usersController.pushNotificationToUser(); 今夜、これを追加しなければなりませんでした。

public void pushNotificationToUser(String notification) {
    applicationScopeBean.pushNotificationToUser(notification, user);
}

applicationScopeBean.pushNotificationToUser(); これはすでに存在していました。このメソッドに変更はありません。

public void pushNotificationToUser(String msg, Users userPushingMessage) {
    for (SessionInfo session : sessions) {
        if (userPushingMessage != null &&
            session.getUser().getUserName().equals(userPushingMessage.getUserName()) &&
            session.getUser().getLastLoginDt().equals(userPushingMessage.getLastLoginDt())) {
            PushContext pushContext = PushContextFactory.getDefault().getPushContext();
            pushContext.push("/" + session.getPushChannelId(),
                             new FacesMessage(FacesMessage.SEVERITY_INFO, "", msg));
            break;
        }
    }
}
于 2013-04-09T08:38:43.943 に答える
0

updateコンポーネントの属性を使用してp:commandButton、ダウンロード後に更新する予定の領域 (この場合は「drawing_table」) を再レンダリングできます。

<p:commandButton update="drawing_table" action="#{document.Download}" value="Download" />
于 2010-08-12T22:13:44.633 に答える
-1

Baluscが答えたように、1 つのリクエストから 2 回レスポンスを取得することはできません。

ダウンロード後にページを更新するには、download link( p:commandbutton) onclick tagで次の Java スクリプトを使用することをお勧めします。

例:

<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />

これにより、1 秒後にページが自動的に更新されます。同時に、更新前に、ダウンロード応答時間に基づいてダウンロード ファイルが取得され、そのスクリプトの秒数が増加します。秒数は、そのダウンロード応答時間よりも小さくてはなりません。

于 2015-04-09T11:15:45.613 に答える