`

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

阅读更多

<script type="text/javascript"> document.body.oncopy = function() { if (window.clipboardData) { setTimeout(function() { var text = clipboardData.getData(&quot;text&quot;); if (text &amp;&amp; text.length &gt; 300) { text = text + &quot;\r\n\n本文来自CSDN博客,转载请标明出处:&quot; + location.href; clipboardData.setData(&quot;text&quot;, text); } }, 100); } } </script><script type="text/javascript"> function StorePage() { d = document; t = d.selection ? (d.selection.type != 'None' ? d.selection.createRange().text : '') : (d.getSelection ? d.getSelection() : ''); void (keyit = window.open('http://www.365key.com/storeit.aspx?t=' + escape(d.title) + '&amp;u=' + escape(d.location.href) + '&amp;c=' + escape(t), 'keyit', 'scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes')); keyit.focus(); }</script>

简介

Web 门户为用户提供了访问各种资源和服务的中心网关。与此同时,它们还为用户提供了与其他用户进行资源共享的平台。从照片到音频、视频文件再到研究用的科学数 据集,用户可以共享任何内容。因此,文件上载是 Web 门户的一种基本的必备功能。

当今的 Web 门户在很大程度上依赖于 Java portlet 技术。虽然很多使用 Ajax 的开发人员都给出了各种各样的文件上载进度条解决方案,但我们还没有听说过哪个是基于 portlet 的。本文展示了如何开发基于 Ajax 的文件上载 portlet,此 portlet 能显示文件上载过程的进度条。此 portlet 对于那些想要共享大型音频、视频和科学文件的人士尤其有用。

要跟上本文的进度,您应该对使用 Java Servlets 和 JavaServer Pages (JSPs) 进行 Web 开发十分熟悉。而且,还必须了解门户和 portlet 技术的开发。当然,如果您对 portlet 技术还不怎么精通,也不要现在就放弃本文,因为您会在本文中看到对 portlet 技术的简单介绍,以及一些有用的资源可用来帮助您加快学习的进程。

在测试本文给出的这个文件上载 portlet 前,可以考虑尝试使用一种遵从 JSR 168 规范的门户框架,比如 IBM® WebSphere® Portal Server、Apache Pluto、eXo 平台或 Liferay Portal。我们在本文中使用的是 Apache Pluto 1.0.1、JDK 5.0 Update 10 和 Apache Ant Version 1.6.5。

portlet 的基本概念

一般地,可以将 portlet 视为一种 Web 组件。Portlet 与 servlet 类似,但前者更关注于应用程序的表示层。portlet 的典型输出是 HTML 片断,这些片断可由 Web 门户随后再组装起来。Portlet 本身由 portlet 容器管理。portlet 的主要特性包括:

  • 多模式 :portlet 可以在不同的模式下有不同的视图。例如,除了查看 模式,portlet 还支持编辑 模式以便用户可以设置其自身的首选项。
  • 多个窗口状态 :portlet 可以最小化、最大化等。
  • 可定制参数 :portlet 可以定义参数,而这些参数可以由用户定制。

要获得有关 portlet 的更多详细信息,可以参考 Java Portlet Specification 1.0,JSR 168(JSR 168 的后续版本 JSR 286 预计会于 2007 年后半年发布,其中包含了一些改进,比如 portlet 间通信和 portlet 过滤器)。相关链接,请参看 参考资料

开始创建文件上载 portlet

文件上载 portlet 的基石是 Apache Commons FileUpload 包(本文也称之为 FileUpload)。除了支持 servlet 内的文件上载外,Apache Commons FileUpload Version 1.1 包还支持 portlet 中的文件上载。本文使用的是 Apache Commons FileUpload 版本 1.2。

基本上,开发文件上载进度条需要两步:

  1. 在服务器端检索文件上载过程
  2. 从门户服务器进行客户端的文件上载检索和显示

文件上载过程的服务器端检索

FileUpload 包支持使用侦听器检索文件上载过程。在文件上载 portlet 的 doUpload() 方法(称为 uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadPortlet , 包括在本文 下载 部分所提供的源文件中),通过调用 setProgressListener() 方法为 PortletFileUpload 设置过程侦听器,如 清单 1 所示:


清单 1. 为文件上载包设置过程侦听器

  1. DiskFileItemFactory factory =  new  DiskFileItemFactory();  
  2. PortletFileUpload pfu = new  PortletFileUpload(factory);  
  3. pfu.setSizeMax(uploadMaxSize); // Maximum upload size   
  4. pfu.setProgressListener(new  FileUploadProgressListener());  

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


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

  1. package uk.ac.dl.esc.gtg.myportlets.fileupload;  
  2.   
  3. import java.text.NumberFormat;  
  4.   
  5. import org.apache.commons.fileupload.ProgressListener;  
  6. import org.apache.commons.logging.Log;  
  7. import org.apache.commons.logging.LogFactory;  
  8.   
  9. public   class  FileUploadProgressListener implements ProgressListener {  
  10.     private   static  Log log = LogFactory.getLog(FileUploadProgressListener. class );  
  11.   
  12.     private   static   long  bytesTransferred = 0;  
  13.   
  14.     private   static   long  fileSize = -100;  
  15.   
  16.     private   long  tenKBRead = -1;  
  17.   
  18.     public  FileUploadProgressListener() {  
  19.     }  
  20.   
  21.     public  String getFileUploadStatus() {  
  22.         // per looks like 0% - 100%, remove % before submission   
  23.         String per = NumberFormat.getPercentInstance().format(  
  24.                 (double ) bytesTransferred / ( double ) fileSize);  
  25.         return  per.substring(0, per.length() - 1);  
  26.     }  
  27.   
  28.     public   void  update( long  bytesRead,  long  contentLength,  int  items) {  
  29.         // update bytesTransferred and fileSize (if required) every 10 KB is   
  30.         // read   
  31.         long  tenKB = bytesRead / 10240;  
  32.         if  (tenKBRead == tenKB)  
  33.             return ;  
  34.         tenKBRead = tenKB;  
  35.   
  36.         bytesTransferred = bytesRead;  
  37.         if  (fileSize != contentLength)  
  38.             fileSize = contentLength;  
  39.     }  
  40.   
  41. }  

文件上载过程的客户端检索

服务器和客户间就文件上载过程的通信是通过使用 Ajax 实现的。我们选用 Direct Web Remoting (DWR) 来提供 portlet 中的 Ajax 支持。DWR 是一种面向 Java 开发人员的理想框架,可用来将 Ajax 引入 Web 开发过程中,原因是它可以让浏览器中的 JavaScript 与服务器端的 Java 对象互动。要在 portlet 中使用 DWR,必须执行以下步骤 (更多有关如何配置 DWR 的信息,请参看 参考资料 ):

  • 通过 WEB-INF/web.xml 配置 DwrServlet (参见 清单 3 )。
  • 在 WEB-INF/dwr.xml 内定义一个或更多的客户机可与之通信的服务器端对象。在 清单 4 中,FileUploadProgressListener 针对 DWR 定义以便客户机可以调用这个自动生成的 JavaScript。此外,只有 getFileUploadStatus 方法可以被客户机调用,另一个公共方法 update 则不允许被访问(请参看 清单 2 )。
  • 将与 DWR 有关的 JavaScript 代码包括在 fileupload-view.jsp(参看 清单 5 )。
  • 将 DWR 库包括在 portlet 应用程序
  • 清单 3. 在 WEB-INF/web.xml 中配置 DwrServlet

    1. <!-- DWR servlet -->   
    2.   < servlet >   
    3.     < servlet-name > dwr-invoker </ servlet-name >   
    4.     < display-name > DWR Servlet </ display-name >   
    5.     < servlet-class > org.directwebremoting.servlet.DwrServlet </ servlet-class >   
    6.     < init-param >   
    7.       < param-name > debug </ param-name >   
    8.       < param-value > false </ param-value >   
    9.     </ init-param >   
    10.   </ servlet >   
    11.   
    12. <!-- DWR servlet mapping -->   
    13.   < servlet-mapping >   
    14.     < servlet-name > dwr-invoker </ servlet-name >   
    15.     < url-pattern > /dwr/* </ url-patter >   
    16.   </ servlet-mappin >   

    清单 4. WEB-INF/dwr.xml

    1. <!DOCTYPE dwr PUBLIC "-//GetAhead Limited//DTD Direct Web Remoting 2.0//EN"  
    2.                      "http://getahead.org/dwr//dwr20.dtd">   
    3.   
    4. < dwr >   
    5.   < allow >   
    6.     < create   creator = "new"   javascript = "FileUploadProgressListener" >   
    7.       < param   name = "class"   
    8.              value = "uk.ac.dl.esc.gtg.myportlets.fileupload.FileUploadProgressListener" />   
    9.       < include   method = "getFileUploadStatus" />   
    10.     </ create >   
    11.   </ allow >   
    12. </ 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

    1. < %@ page  session = "false"  % >   
    2. < %@ page  contentType = "text/html"  % >   
    3. < %@ page  import = "javax.portlet.PortletURL"  % >   
    4. < %@ taglib  uri = "http://java.sun.com/portlet"   prefix = "portlet"  % >   
    5. < portlet:defineObjects />   
    6.   
    7. < mce:script   type = "text/javascript"   
    8.         src =' < %= renderResponse.encodeURL(renderRequest.getContextPath()  
    9.                 + "/dwr/interface/FileUploadProgressListener.js") %> <!--  
    10. '>    
    11. // --> </ mce:script >   
    12.   
    13. < mce:script   type = "text/javascript"   
    14.         src =' < %= renderResponse.encodeURL(renderRequest.getContextPath()  
    15.                 + "/dwr/engine.js") %> <!--  
    16. '>    
    17. // --> </ mce:script >   
    18.   
    19. < mce:script   type = "text/javascript"   
    20.         src =' < %= renderResponse.encodeURL(renderRequest.getContextPath()  
    21.                 + "/dwr/util.js") %> <!--  
    22. '>    
    23. // --> </ mce:script >   
    24.   
    25. < mce:script   type = "text/javascript" > <!--  
    26.   function fileupload_ajax_query_upload_status() {  
    27.     FileUploadProgressListener.getFileUploadStatus  
    28.   
    29.                  (fileupload_ajax_show_upload_status);  
    30.     return true;  
    31.   }  
    32.   
    33.   function fileupload_ajax_show_upload_status(status) {  
    34.     if (status  == "100")  
    35.       document.getElementById("fileupload_progress").innerHTML   
    36.                                        ="File successfully uploaded" ;  
    37.     else {  
    38.       document.getElementById("progressBar").style.display  =  "block" ;  
    39.       document.getElementById("fileupload_progress").innerHTML =  
    40.                                        "Uploading file: "  + status  
    41.                                        + "% completed, please wait...";  
    42.       document.getElementById("progressBarBoxContent").style.width  =  
    43.                                        parseInt (status * 3.5) + "px";  
    44.       setTimeout(fileupload_ajax_query_upload_status, 2000);  
    45.     }  
    46.   
    47.     return true;  
    48.   }  
    49. // --> </ mce:script >   
    50.   
    51. < mce:style   type = "text/css" > <!--  
    52.   #progressBar {padding-top: 5px;}  
    53.   #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;}  
    54.   #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444;  
    55.                                        background: #9ACB34;}  
    56. --> </ mce:style > < style   type = "text/css"   mce_bogus = "1" >   #progressBar {padding-top: 5px;}  
    57.   #progressBarBox {width: 350px; height: 20px; border: 1px insert; background: #eee;}  
    58.   #progressBarBoxContent {width: 0; height: 20px; border-right: 1px solid #444;  
    59.                                        background: #9ACB34;}</ style >   
    60.   
    61. < h4 > File Upload </ h4 >   
    62.   
    63. <!-- the upload form -->   
    64. < % PortletURL  pUrl  =  renderResponse .createActionURL();  
    65.  %>   
    66. < form   action = "<%= pUrl.toString() %>"   
    67.          enctype = "multipart/form-data"   method = "post"   
    68.      onsubmit = "setTimeout('fileupload_ajax_query_upload_status()', 1000)" >   
    69.        
    70.   < input   type = "file"   name = "fileupload_upload"   value = "Upload File" >   
    71.   < input   type = "submit"   value = "Upload" >   
    72. </ form >   
    73.   
    74. < %-- file upload progress bar --% >   
    75. < div   id = "fileupload_progress" > </ div >   
    76. < div   id = "progressBar"   style = "display: none;"   mce_style = "display: none;" >   
    77.   < div   id = "progressBarBoxContent" > </ div >   
    78. </ 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:

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

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

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

    测试文件上载 portlet

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

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

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


    图 2. 文件上载 portlet 正在上载文件

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

    此技术的其他应用

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

    结束语

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

    分享到:
    评论

    相关推荐

      文件上载Portlet源代码

      文件上载Portlet是Web应用程序中的一个组件,主要用于在用户界面上接收并处理用户上传的文件。Portlet是Java Portlet API定义的一种可重用、可组合的Web部件,它在门户环境中运行,如Liferay、Pluto等。在这个特定的...

      dwr和简单的文件上传

      当用户选择文件后,DWR会通过AJAX调用`uploadFile`方法,将文件数据发送到服务器。 ```html ()"&gt;上传 &lt;script src="/dwr/interface/FileUploadService.js"&gt; function upload() { var file = document....

      DWR 实现ajax上传的小实例

      通过DWR,我们可以轻松地在Java后端和JavaScript前端之间建立实时通信,实现文件的Ajax上传。这个小实例是初学者了解DWR功能的一个好起点,通过实际操作,你可以深入理解DWR的工作原理以及如何利用它来提升Web应用的...

      利用DWR实现文件上传进度条

      在Web开发中,文件上传是常见的功能,但如何实时显示文件上传进度给用户带来更好的交互体验呢?本文将详细介绍如何利用Direct Web Remoting (DWR)来实现这一功能。DWR是一种Java库,它允许JavaScript和服务器端Java...

      dwr实现ajax功能ajax+dwr

      **Ajax**的核心是利用JavaScript进行异步数据请求,通过XMLHttpRequest对象与服务器进行通信,通常用于创建更快速、更互动的用户界面。然而,Ajax的缺点在于跨域限制和复杂的JavaScript代码编写。DWR则简化了这个...

      my_employee_study.rar_Employee Stud_ajax_dwr_dwr ajax_上传 Java

      【标题】"my_employee_study.rar_Employee Stud_ajax_dwr_dwr ajax_上传 Java" 提供了一个关于员工学习的场景,特别关注的是AJAX、DWR技术以及Java在文件上传中的应用。这个压缩包包含了作者在公司近两个月内通过...

      dwr3ReverseAjax示例

      在这个“dwr3ReverseAjax示例”中,我们将深入探讨如何利用DWR 3.x版本来构建一个基于Ajax的简单Web聊天应用。 首先,DWR的核心功能是通过HTTP协议实现在客户端JavaScript和服务器端Java之间的远程方法调用(Remote...

      采用dwr+Ajax和struts开发文件上传进度条(网络文章)

      采用dwr+Ajax和struts开发文件上传进度条(网络文章)

      DWR 视频教程 使用DWR开发AJAX For JavaEE

      9. **实战项目**:“[浪曦原创]零散视频三 使用DWR开发AJAX For J2EE(JustCode).wrf”可能是一个实际操作视频,详细演示如何使用DWR构建一个简单的AJAX应用,通过观看可以加深对上述理论知识的理解。 10. **资源...

      DWR jar包 ajax必备

      DWR jar包 ajax必备,非常实用的开源工具

      采用dwr+ajax和struts开发文件上传进度条

      ### 采用DWR+AJAX和Struts开发文件上传进度条 #### 一、概述 在Web应用开发中,文件上传是一项常见的功能需求。传统的文件上传方式无法提供良好的用户体验,尤其是对于大文件上传时,用户很难了解到上传进度,进而...

      dwr和ajax技术

      DWR是基于JavaScript的,它扩展了Ajax的功能,提供了更便捷的远程调用Java对象的方式。Ajax则依赖于JavaScript来实现客户端的动态更新。JavaScript作为Web开发中的基础语言,是实现DWR和Ajax功能的关键。 **压缩包...

      即时通讯DWR Reverse Ajax

      使用DWR实现Reverse Ajax,首先需要在服务器端配置DWR,包括创建DWR的配置文件dwr.xml,设置允许访问的Java方法。然后在客户端,使用JavaScript的DWR API创建连接并注册回调函数,以接收服务器推送的数据。在服务器...

      利用dwr实现Ajax

      DWR简化了Ajax开发,使得开发者可以方便地调用服务器端的方法,就像它们是本地JavaScript函数一样。以下是对"利用DWR实现Ajax"这一主题的详细说明: 1. **DWR的基本概念**: - DWR是一种基于HTTP协议的远程方法...

      dwr的例子 反向AJAX 实现时时提醒

      总的来说,DWR通过反向AJAX技术简化了服务器和客户端之间的通信,使得开发实时更新的应用变得更加便捷。通过学习和理解DWR的工作原理以及如何在项目中应用,你可以创建出更加动态、响应式的Web应用程序。

      DWR:java ajax application

      DWR (Direct Web Remoting) 是一种基于Ajax的Java框架,它简化了JavaScript与Java之间的通信过程,使得开发者能够更加高效地构建富客户端应用程序。 #### 二、DWR简介 DWR由Joe Walker创建,首次发布于2003年,是...

      使用DWR开发AJAX For J2EE

      6. **A051]使用DWR开发AJAX For J2EE.wrf** 文件可能是一个Web资源文件,用于在Web浏览器中展示DWR开发的AJAX示例。 7. **dwrajax.js** 文件可能是DWR自动生成的JavaScript接口文件,包含了对服务器端DWR相关方法...

      dwr.rar_dwr_dwr ajax_dwr 实现 联动 标签

      在“dwr.rar_dwr_dwr ajax_dwr 实现 联动 标签”这个项目中,我们将探讨如何利用DWR和AJAX技术来创建一个动态的、具有联动效果的标签系统。 1. **DWR基础**: DWR的核心组件包括一个服务器端的Servlet(DWR Engine...

      DWR + Servlet 实现文件上传功能

      本文将深入探讨如何利用DWR与Servlet实现在Web应用程序中添加文件上传功能,并且特别关注如何实现进度条展示。 DWR是一种JavaScript库,它允许在浏览器和服务器之间进行双向通信,使得动态更新页面变得更加容易。...

    Global site tag (gtag.js) - Google Analytics