java 下载后如何刷新页面
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3471880/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to refresh a page after download
提问by Thang Pham
I have a commandButton that will invoke a function to download a file (standard stuffs like InputStream, BufferedOutputStream...) After download success, at the end of the function, I change some values of the current object and persist it into database. All of these work correctly. Now when file is done downloading, the content of the page is not updated. I have to hit refresh for me to see updated content. Please help. Below are the basic structure of my code
我有一个命令按钮,它将调用一个函数来下载一个文件(标准的东西,如InputStream,BufferedOutputStream...)下载成功后,在函数的末尾,我更改了当前对象的一些值并将其保存到数据库中。所有这些都可以正常工作。现在当文件下载完成时,页面的内容不会更新。我必须点击刷新才能看到更新的内容。请帮忙。以下是我的代码的基本结构
document: Managed BeangetDrawings(): method return a list of Drawing (entity class)CheckedOutBy: attribute of Entity Drawing
document:托管Bean getDrawings():方法返回绘图(实体类)的列表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" />
Inside my Managed Bean
在我的托管 Bean 中
public void Download(){
Drawing drawing = getCurrentDrawing();
//Download drawing
drawing.setCheckedOutBy("Some Text");
sBean.merge(drawing); //Update "Some Text" into CheckedOutBy field
}
采纳答案by BalusC
You'd basically like to let the client fire tworequests. One to retrieve the download and other to refresh the new page. They cannot be done in a single HTTP request. Since the download needs to be taken place synchronously and there's no way to hook on complete of the download from the client side on, there are no clean JSF/JS/Ajax ways to update a component on complete of the download.
您基本上希望让客户端发出两个请求。一个用于检索下载,另一个用于刷新新页面。它们不能在单个 HTTP 请求中完成。由于下载需要同步进行,并且无法从客户端挂钩下载完成,因此没有干净的 JSF/JS/Ajax 方法在下载完成时更新组件。
Your best JSF-bet with help of PrimeFaces is <p:poll>
在 PrimeFaces 的帮助下,您最好的 JSF 投注是 <p:poll>
<h:outputText id="checkedOutBy" value="#{item.checkedOutBy}"/>
...
<p:poll id="poll" interval="5" update="checkedOutBy" />
or <p:push>
或者 <p:push>
<p:push onpublish="javaScriptFunctionWhichUpdatesCheckedOutBy" />
Polling is easy, but I can imagine that it adds unnecessary overhead. You cannot start it using standard JSF/PrimeFaces components when the synchronous download starts. But you can stop it to let it do a self-check on the renderedattribute. Pushing is technically the best solution, but tougher to get started with. PrimeFaces explains its use however nicely in chapter 6 of the User Guide.
轮询很容易,但我可以想象它会增加不必要的开销。当同步下载开始时,您不能使用标准 JSF/PrimeFaces 组件启动它。但是您可以停止它,让它对rendered属性进行自检。推动是技术上最好的解决方案,但更难开始。PrimeFaces 在用户指南的第 6 章很好地解释了它的用法。
回答by Howard
Well, I decided to go with BalusC's answer/recommendation above, and decided to share my code here for people that may stop by here, 'later'. FYI, my environment details are below:
好吧,我决定采用上面 BalusC 的答案/建议,并决定在这里分享我的代码,供可能会在“稍后”来这里的人使用。仅供参考,我的环境详细信息如下:
TomEE 1.6.0 SNAPSHOT (Tomcat 7.0.39), PrimeFaces 3.5 (PrimeFaces Push), Atmosphere 1.0.13 snapshot (1.0.12 is latest stable version)
TomEE 1.6.0 SNAPSHOT (Tomcat 7.0.39)、PrimeFaces 3.5 (PrimeFaces Push)、Atmosphere 1.0.13 快照(1.0.12 是最新的稳定版本)
First of all, i am using p:fileDownload with p:commandLink.
首先,我使用 p:fileDownload 和 p:commandLink。
<p:commandLink value="Download" ajax="false"
actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}">
<p:fileDownload value="#{driverWorksheet.file}"/>
</p:commandLink>
Since I have the xhtml above, and since p:fileDownload does not allow oncomplete="someJavaScript()" to be executed, I decided to use PrimeFaces Push to push message to client, to trigger the javascript necessary to unblock the UI, because UI was being blocked whenever I click the commandLink to download file, and for many months, I didn't know how to solve this.
由于我有上面的 xhtml,并且由于 p:fileDownload 不允许执行 oncomplete="someJavaScript()",我决定使用 PrimeFaces Push 将消息推送到客户端,以触发解锁 UI 所需的 javascript,因为 UI每当我单击 commandLink 下载文件时都会被阻止,并且有好几个月了,我不知道如何解决这个问题。
Since I already am using PrimeFaces Push, I had to tweak the following on the client side:
由于我已经在使用 PrimeFaces Push,我不得不在客户端调整以下内容:
.js file; contains method that handles messages pushed from server to client
.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; contains p:socket component (PrimeFaces Push); i recommend all of the following, if you're are implementing FacesMessage example of PrimeFaces Push
索引.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}" />
Months (or maybe a year-or-so) ago, i found it necessary to add the following to the commandLink that wraps p:fileDownload, which will refresh the file/stream on server, so you can click the file as many times as you need and download the file again and again without refreshing the page via F5/refresh key on keyboard (or similar on mobile device)
几个月(或者一年左右)前,我发现有必要将以下内容添加到包装 p:fileDownload 的 commandLink 中,这将刷新服务器上的文件/流,因此您可以多次单击该文件您需要并一次又一次地下载文件,而无需通过键盘上的 F5/刷新键(或移动设备上的类似键)刷新页面
actionListener="#{pf_ordersController.refreshDriverWorksheetsToDownload()}"
That bean method is referenced whenever enduser clicks the commandLink, to download file, so this was perfect spot to 'push' a message from server to client, to trigger javascript on client, to unblock UI.
每当最终用户单击 commandLink 以下载文件时,都会引用该 bean 方法,因此这是将消息从服务器“推送”到客户端、在客户端上触发 javascript 以取消阻止 UI 的最佳位置。
Below are the bean methods in my app that gets the job done. :)
下面是我的应用程序中完成工作的 bean 方法。:)
pf_ordersController.refreshDriverWorksheetsToDownload()
pf_ordersController.refreshDriverWorksheetsToDownload()
public String refreshDriverWorksheetsToDownload() {
String returnValue = prepareDriverWorksheetPrompt("download", false);
usersController.pushNotificationToUser("displayLoadingImage(false)");
return returnValue;
}
usersController.pushNotificationToUser(); i had to add this one, tonight.
usersController.pushNotificationToUser(); 今晚我不得不添加这个。
public void pushNotificationToUser(String notification) {
applicationScopeBean.pushNotificationToUser(notification, user);
}
applicationScopeBean.pushNotificationToUser(); this already existed, no change to this method.
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;
}
}
}
回答by Jose Diaz
You could use the updateattribute of the p:commandButtoncomponent to re-render the area that you intend to refresh after download, in this case your "drawing_table".
您可以使用组件的update属性p:commandButton重新渲染下载后要刷新的区域,在这种情况下是“drawing_table”。
<p:commandButton update="drawing_table" action="#{document.Download}" value="Download" />
回答by Shanmuganathan
As Baluscanswered, we cannot get response twice from a single request.
正如Balusc回答的那样,我们无法从单个请求中获得两次响应。
To refresh a page after download, better use the following java script in download link(p:commandbutton) onclick tag.
要在下载后刷新页面,最好在下载链接 ( p:commandbutton) onclick 标签中使用以下 java 脚本。
Example:
例子:
<p:commandButton ajax="false" icon="ui-icon-arrowstop-1-s" onclick="setTimeout('location.reload();', 1000);" action="#{managedBean.downloadMethod}" />
this will automatically refresh the page after 1 second, at the same time i.e. before refresh, you will get the download file, based on your download response time, increase the seconds in that script. Seconds should not less than that download response time.
这将在 1 秒后自动刷新页面,同时即在刷新之前,您将获得下载文件,根据您的下载响应时间,增加该脚本中的秒数。秒应该不少于那个下载响应时间。

