首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Ajax >

利用 DWR 开发基于 Ajax 的文件下载 portlet

2012-11-08 
利用 DWR 开发基于 Ajax 的文件上载 portletDiskFileItemFactory factory new DiskFileItemFactory()Po

利用 DWR 开发基于 Ajax 的文件上载 portlet

DiskFileItemFactory factory = new DiskFileItemFactory();PortletFileUpload pfu = new PortletFileUpload(factory);pfu.setSizeMax(uploadMaxSize); // Maximum upload sizepfu.setProgressListener(new FileUploadProgressListener());

侦听器 FileUploadProgressListener(参见 清单 2)可实现 org.apache.commons.fileupload.ProgressListener 接口。update() 方法自动由 FileUpload 包调用以刷新有关所传输字节数的最新信息。在本文的实现中,每传输 10KB 数据则更新一次进度。这有助于防止更新进行得太频繁。 getFileUploadStatus() 方法用来计算当前文件上载进度,可由客户机通过 DWR 调用(在下一节讨论)。


清单 2. 检索文件上载过程的文件上载侦听器

package uk.ac.dl.esc.gtg.myportlets.fileupload;import java.text.NumberFormat;import org.apache.commons.fileupload.ProgressListener;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;public class FileUploadProgressListener implements ProgressListener {private static Log log = LogFactory.getLog(FileUploadProgressListener.class);private static long bytesTransferred = 0;private static long fileSize = -100;private long tenKBRead = -1;public FileUploadProgressListener() {}public String getFileUploadStatus() {// per looks like 0% - 100%, remove % before submissionString per = NumberFormat.getPercentInstance().format((double) bytesTransferred / (double) fileSize);return per.substring(0, per.length() - 1);}public void update(long bytesRead, long contentLength, int items) {// update bytesTransferred and fileSize (if required) every 10 KB is// readlong tenKB = bytesRead / 10240;if (tenKBRead == tenKB)return;tenKBRead = tenKB;bytesTransferred = bytesRead;if (fileSize != contentLength)fileSize = contentLength;}}

<!-- DWR servlet --> <servlet> <servlet-name>dwr-invoker</servlet-name> <display-name>DWR Servlet</display-name> <servlet-class>org.directwebremoting.servlet.DwrServlet</servlet-class> <init-param> <param-name>debug</param-name> <param-value>false</param-value> </init-param> </servlet><!-- DWR servlet mapping --> <servlet-mapping> <servlet-name>dwr-invoker</servlet-name> <url-pattern>/dwr/*</url-patter> </servlet-mappin>

清单 4. WEB-INF/dwr.xml

<!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN" "http://getahead.org/dwr//dwr20.dtd"><dwr> <allow> <create creator="new" javascript="FileUploadProgressListener"> <param name="class" value="uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadProgressListener"/> <include method="getFileUploadStatus"/> </create> </allow></dwr>

清单 5 所示的 JSP 文件 fileupload-view.jsp 展示了 DWR 如何有助于从服务器端检索文件上载过程。一旦选中了文件并单击了 Upload 按钮(参看 图 1),fileupload_ajax_query_upload_status() 方法会被即刻调用。此方法之后会以异步模式调用 FileUploadProgressListenergetFileUploadStatus() 方法(参见 清单 2)。DWR 的妙处就在于此:客户机可以和服务器端的 Java 对象交互。一旦收到响应,fileupload_ajax_show_upload_status() 方法会被调用以刷新此过程。如果文件上载没有完成,更新后的过程就会在两秒种之后检索。

清单 5. 文件上载 portlet JSP 文件 —— fileupload-view.jsp

<%@ page session="false" %><%@ page contentType="text/html" %><%@ page import="javax.portlet.PortletURL" %><%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %><portlet:defineObjects/><mce:script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+ "/dwr/interface/FileUploadProgressListener.js") %><!--'> // --></mce:script><mce:script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+ "/dwr/engine.js") %><!--'> // --></mce:script><mce:script type="text/javascript" src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+ "/dwr/util.js") %><!--'> // --></mce:script><mce:script type="text/javascript"><!-- function fileupload_ajax_query_upload_status() { FileUploadProgressListener.getFileUploadStatus (fileupload_ajax_show_upload_status); return true; } function fileupload_ajax_show_upload_status(status) { if (status == "100") document.getElementById("fileupload_progress").innerHTML ="File successfully uploaded"; else { document.getElementById("progressBar").style.display = "block"; document.getElementById("fileupload_progress").innerHTML= "Uploading file: " + status + "% completed, please wait..."; document.getElementById("progressBarBoxContent").style.width = parseInt(status * 3.5) + "px"; setTimeout(fileupload_ajax_query_upload_status, 2000); } return true; }// --></mce:script><mce:style type="text/css"><!-- #progressBar {padding-top: 5px;} #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;} #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444; background: #9ACB34;}--></mce:style><style type="text/css" mce_bogus="1"> #progressBar {padding-top: 5px;} #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;} #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444; background: #9ACB34;}</style><h4>File Upload</h4><!-- the upload form --><% PortletURL pUrl = renderResponse.createActionURL(); %><form action="<%= pUrl.toString() %>" enctype="multipart/form-data" method="post" onsubmit="setTimeout('fileupload_ajax_query_upload_status()', 1000)"> <input type="file" name="fileupload_upload" value="Upload File"> <input type="submit" value="Upload"></form><%-- file upload progress bar --%><div id="fileupload_progress"></div><div id="progressBar" style="display: none;" mce_style="display: none;"> <div id="progressBarBoxContent"></div></div>

用 Apache Pluto 部署和测试文件上载 portlet

此过程的下一步是用 Apache Pluto 1.0.1. 部署和测试文件上载 portlet(注意:本文使用的是二进制版本)。

代码编译和部署

本文附带的可下载的 portlet 源代码同时还提供有 Ant 脚本,以便能够编译 portlet 和构建部署所需要的 .war 文件。首先,必须将如下的二进制文件复制到源代码根目录下的 lib 目录:

commons-fileupload-1.2/commons-fileupload-1.2.jar commons-io-1.3/commons-io-1.3.jar commons-logging-1.0.4/commons-logging-1.0.4.jar dwr-2.0.1/dwr.jar portletapi-1.0/portlet.jar servletapi-2.4/servletapi-2.4.jar

之后,就可以运行 ant buildant war 以编译代码和相应构建部署所需的 .war 文件。如果一切顺利,myportlets-fileupload.war 就会出现在 dist 目录下。执行如下步骤以利用 Apache Pluto 1.0.1 部署 portlet:

    启动 Apache Tomcat 并访问 http://localhost:8080/pluto/portal。 单击 Pluto 屏幕左侧的 Admin 链接来部署此 portlet。 找到 myportlets-fileupload.war,然后单击 Submit。 定义 portlet 标题、描述和布局,然后单击 Submit。 再次单击所显示页面上的 Submit

现在,系统会提示您或者重启 Tomcat,或者单击链接 Hot deploy myportlets-fileupload portlet application。我们建议您单击链接 Hot deploy myportlets-fileupload portlet application。之后,此 portlet 会被加载,如 图 1 所示:

图 1. 运行于 Apache Pluto 中的文件上载 portlet

利用 DWR 开发基于 Ajax 的文件下载 portlet

测试文件上载 portlet

一旦部署完此 portlet 之后,就可以上载文件了。要显示出此进度条,应该从计算机而不是从门户服务器访问此 portlet。执行如下步骤上载文件:

    单击 Browse... 按钮选择要上载的文件。 单击 Upload 按钮上载选中的文件。在文件上载期间,会显示并更新进度条(参见 图 2)。

如果从安装了 Pluto 的计算机测试此 portlet,就不会看到进度条,原因是所设置的上载大小最大为 20MB。通过在 WEB-INF/portlet.xml 文件内更改 fileupload_upload_maxsize 可以改变此上载大小。


图 2. 文件上载 portlet 正在上载文件
利用 DWR 开发基于 Ajax 的文件下载 portlet

在我们的 portlet 中,所上载的文件作为磁盘文件保存在 java.io.tmpdir 下 —— 比如,位于 $PLUTO_HOME 或 $CATALINA_HOME 下的 temp。请注意在实际的 Web 应用程序中,可能还会需要进一步的处理。比如,所上载的文件可能需要存储在数据库中以备后用;如果是图像文件,它就有可能显示在 Web 浏览器内。

此技术的其他应用

本文所探讨的技术已经被成功应用到文件传输 portlet,该 protlet 采用 GridFTP 协议管理两个第三方数据网格节点之间的大型数据集。

结束语

本文讨论了如何使用 Ajax 部署文件上载 portlet 以显示进度条。介绍了如何利用过程侦听器进行服务器端的文件上载过程检索,如何使用 DWR 从门户服务器进行客户端的文件上载检索,以及如何将进度条呈现给终端用户。此 portlet 对于共享诸如音频、视频文件和科学数据这类大型数据集尤其有用。本文也展示了使用 DWR 为 JSR 168 portlet 提供 Ajax 支持是多么地容易。

热点排行