转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> JAVA开发 >> 正文
AJAX+JSF组件实现高性能的文件上载         ★★★★

AJAX+JSF组件实现高性能的文件上载

作者:闵涛 文章来源:闵涛的学习笔记 点击数:945 更新时间:2009/4/22 23:32:58
  一、 引言

  基于浏览器的文件上传,特别是对于通过<input type="file">标签包含到Web页面来实现上传的情况,还存在较严重的性能问题。我们知道,超过10MB的上传文件经常导致一种非常痛苦的用户体验。一旦用户提交了文件,在浏览器把文件上传到服务器的过程中,界面看上去似乎处于静止状态。由于这一切发生在后台,所以许多没有耐心的用户开始认为服务器"挂"了,因而再次提交文件,这当然使得情况变得更糟糕。

  为了尽可能使得文件上传感觉更友好些,一旦用户提交文件,许多站点将显示一个中间过程动画(例如一旋转图标)。尽管这一技术在上传提交到服务器时起一些作用,但它还是提供了太少的有关文件上传状态的信息。解决这个问题的另外一种尝试是实现一个applet——它通过FTP把文件上传到服务器。这一方案的缺点是:限制了你的用户,必须要有一个支持Java的浏览器。

  在本文中,我们将实现一个具有AJAX能力的组件——它不仅实现把文件上传到服务器,而且"实时地"监视文件上传的实际过程。
  二、 实现该组件

  首先,我们分析创建多部分过滤的过程,它将允许我们处理并且监视文件上传。然后,我们将继续实现JavaServer Faces(JSF)组件-它将提供给用户连续的回馈,以支持AJAX的进度条方式。

  (一) 多部分过滤:UploadMultipartFilter

  多部分过滤的任务是拦截到来的文件上传并且把该文件写到一个服务器上的临时目录中。同时,它还将监视接收的字节数并且确定已经上载该文件的程度。幸运的是,现在有一个优秀的Jakarta-Commons开源库可以利用(FileUpload),可以由它来负责分析一个HTTP多部分请求并且把文件上传到服务器。我们要做的是扩展该库并且加入我们需要的"钩子"来监视已经处理了多少字节。

public class UploadMultipartFilter implements Filter{
 public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)
 throws IOException, ServletException {
  HttpServletRequest hRequest = (HttpServletRequest)request;
  //检查是否我们在处理一个多部分请求
  String contentHeader = hRequest.getHeader("content-type");
  boolean isMultipart = ( contentHeader != null && contentHeader.indexOf("multipart/form-data") != -1);
  if(isMultipart == false){
   chain.doFilter(request,response);
  }else{
   UploadMultipartRequestWrapper wrapper = new UploadMultipartRequestWrapper(hRequest);
   chain.doFilter(wrapper,response);
  }
  ...
 }
  正如你所见,UploadMultipartFilter类简单地检查了当前的请求是否是一个多部分请求。如果该请求不包含文件上传,该请求将被传递到请求链中的下一个过滤,而不进行任何另外的处理。否则,该请求将被包装在一个UploadMultipartRequestWrapper中。

  (二) UploadMultipartRequestWrapper类

public class UploadMultipartRequestWrapper
extends HttpServletRequestWrapper{
 private Map<String,String> formParameters;
 private Map<String,FileItem> fileParameters;
 public UploadMultipartRequestWrapper(HttpServletRequest request) {
  super(request);
  try{
   ServletFileUpload upload = new ServletFileUpload();
   upload.setFileItemFactory(new ProgressMonitorFileItemFactory(request));
   List fileItems = upload.parseRequest(request);
   formParameters = new HashMap<String,String>();
   fileParameters = new HashMap<String,FileItem>();
   for(int i=0;i<fileItems.size();i++){
    FileItem item = (FileItem)fileItems.get(i);
    if(item.isFormField() == true){
     formParameters.put(item.getFieldName(),item.getString());
    }else{
     fileParameters.put(item.getFieldName(),item);
     request.setAttribute(item.getFieldName(),item);
    }
   }
   }catch(FileUploadException fe){
    //请求时间超过-用户可能已经转到另一个页面。
    //作一些记录
    //...
   }
   ...
  在UploadMultipartRequestWrapper类中,我们将初始化ServletFileUpload类,它负责分析我们的请求并且把文件写到服务器上的缺省临时目录。ServletFileUpload实例针对在该请求中遇到的每一个字段创建一个FileItem实例(它们包含文件上传和正常的表单元素)。之后,一个FileItem实例用于检索一个提交字段的属性,或者,在文件上传的情况下,检索一个到底层的临时文件的InputStream。总之,UploadMultipartRequestWrapper负责分析该文件并且设置任何FileItem-它在该请求中把文件上传描述为属性。然后,这些属性由JSF组件所进一步收集,而正常表单字段的行为保持不变。

  默认情况下,通用FileUpload库将使用DiskFileItems类的实例来处理文件上传。尽管DiskFileItem在处理整个临时文件业务时是很有用的,但在准确监视该文件已经处理程度方面存在很少支持。自版本1.1以来,通用FileUpload库能够使开发者指定用于创建FileItem的工厂。我们将使用ProgressMonitorFileItemFactory和ProgressMonitorFileItem类来重载缺省行为并监视文件上传过程。

  (三) ProgressMonitorFileItemFactory类

public class ProgressMonitorFileItemFactory extends DiskFileItemFactory {
 private File temporaryDirectory;
 private HttpServletRequest requestRef;
 private long requestLength;
 public ProgressMonitorFileItemFactory(HttpServletRequest request) {
  super();
  temporaryDirectory = (File)request.getSession().getServletContext().getAttribute("javax.servlet.context.tempdir");
  requestRef = request;
  String contentLength = request.getHeader("content-length");
  if(contentLength != null){requestLength = Long.parseLong(contentLength.trim());}
 }
 public FileItem createItem(String fieldName, String contentType,boolean isFormField, String fileName) {
  SessionUpdatingProgressObserver observer = null;
  if(isFormField == false) //这必须是一文件上传.
   observer = new SessionUpdatingProgressObserver(fieldName,fileName);
   ProgressMonitorFileItem item = new ProgressMonitorFileItem(
     fieldName,contentType,isFormField,
     fileName,2048,temporaryDirectory,
     observer,requestLength);
    return item;
 }
 ...
 public class SessionUpdatingProgressObserver implements ProgressObserver {
  private String fieldName;
  private String fileName;
  ...
  public void setProgress(double progress) {
   if(request != null){
    request.getSession().setAttribute("FileUpload.Progress."+fieldName,progress);
    request.getSession().setAttribute("FileUpload.FileName."+fieldName,fileName);
   }
  }
 }
}
  ProgressMonitorFileItemFactory Content-Length头由浏览器设置并且假定它是被设置的上传文件的精确长度。这种确定文件长度的方法确实限制了你在每次请求中上传的文件-如果有多个文件在该请求中被编码的话,不过这个值是不精确的。这是由于,浏览器仅仅发送一个Content-Length头,而不考虑上传的文件数目。

  除了创建ProgressMonitorFileItem实例之外,ProgressMonitorFileItemFactory还注册了一个ProgressObserver实例,它将由ProgressMonitorFileItem来发送文件上传过程中的更新。我们所使用的ProgressObserver的实现(SessionUpdatingProgressObserver)针对被提交字段的id把进度百分数设置到用户的会话中。然后,这个值可以由JSF组件存取以便把更新发送给用户。
 


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台