下载后如何刷新页面

问题描述 投票:0回答:5

我有一个命令按钮,它将调用一个函数来下载文件(标准的东西,如

InputStream
BufferedOutputStream
...)下载成功后,在函数结束时,我更改当前对象的一些值并保留将其存入数据库。所有这些都可以正常工作。现在,当文件下载完成时,页面内容不会更新。我必须点击刷新才能看到更新的内容。请帮忙。以下是我的代码的基本结构

document
:托管 Bean
getDrawings()
:方法返回Drawing列表(实体类)
CheckedOutBy
:实体的属性
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
}
jsf primefaces refresh
5个回答
5
投票

在 JS API 中使用

PrimeFaces.monitorDownload()
并在结束回调中调用
location.reload()

<p:commandButton ... onclick="PrimeFaces.monitorDownload(null, stopDownload)">
    <p:fileDownload value="#{fileDownloadController.file}"/>
</p:commandButton>
function stopDownload() {
    location.reload();
}

如果您尚未使用 PrimeFaces 4.x,请升级。


2
投票

好吧,我决定采用上面 BalusC 的答案/建议,并决定在这里分享我的代码,以便“稍后”可能会在这里停留的人们。仅供参考,我的环境详细信息如下:

TomEE 1.6.0 SNAPSHOT (Tomcat 7.0.39)、PrimeFaces 3.5 (PrimeFaces Push)、Atmosphere 1.0.13 快照(1.0.12 是最新稳定版本)

首先,我使用 p:fileDownload 和 p:commandLink。

<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,因为每当我单击命令链接下载文件时,UI 就会被阻止,几个月来我都不知道如何解决这个问题。

由于我已经在使用 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}" />

几个月(或者大约一年)前,我发现有必要将以下内容添加到包装 p:fileDownload 的 commandLink 中,这将刷新服务器上的文件/流,以便您可以多次单击该文件根据需要一次又一次下载文件,无需通过键盘上的 F5/刷新键(或移动设备上的类似键)刷新页面

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

每当最终用户单击 commandLink 下载文件时,都会引用该 bean 方法,因此这是将消息从服务器“推送”到客户端、在客户端上触发 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;
        }
    }
}

0
投票

您可以使用

update
组件的
p:commandButton
属性来重新渲染下载后要刷新的区域,在本例中是您的“drawing_table”。

<p:commandButton update="drawing_table" action="#{document.Download}" value="Download" />

0
投票

我还选择了@Balusc建议的投票方式。 为了将开销降至最低,我仅在按下按钮后才开始轮询(autoStart =“false”):

<h:form id='formOne'>
    <h:selectOneMenu id="checkedOutBy" value="#{bean.items}".../>
     ....
    <p:commandButton value="Download PDF" action="#{controller.downloadPdf}" onclick="startPolling();" ajax="false" />
     ....
    <p:poll interval="5" update="checkedOutBy" autoStart="false" widgetVar="pollWidget" oncomplete="checkPollCount()"/>
</h:form>

并为被调用函数添加此 JavaScript checkPollCountstartPolling:

<script type="text/javascript"> 
    let pollCount = 0;
    const maxPollCount = 10; // max Poll-tries

    function checkPollCount() {

        var value= $('#formOne\\:checkedOutBy:selected').val(); 

        if (value === 'expectedValue after Change') {
            PF('pollWidget').stop(); 
            return;
        }
        pollCount++;
        if (pollCount >= maxPollCount) {
            PF('pollWidget').stop(); 
            pollCount = 0; 
        }
    }
   
    function startPolling() {
        pollCount = 0; 
        PF('pollWidget').start(); 
    }
</script>

-1
投票

正如 Balusc 所回答的那样,我们无法从单个请求中获得两次响应。

要在下载后刷新页面,最好在下载链接中使用以下java脚本(

p:commandbutton
)onclick标签

示例:

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

这将在1秒后自动刷新页面,同时即在刷新之前,您将获得下载文件,根据您的下载响应时间,增加该脚本中的秒数。 秒数不应小于下载响应时间。

© www.soinside.com 2019 - 2024. All rights reserved.