AJAX JSF组件实现高性能的文件上载
2008-02-23 08:07:17来源:互联网 阅读 ()
基于浏览器的文件上传,特别是对于通过<input type="file">标签包含到Web页面来实现上传的情况,还存在较严重的性能问题。我们知道,超过10MB的上传文件经常导致一种非常痛苦的用户体验。一旦用户提交了文件,在浏览器把文件上传到服务器的过程中,界面看上去似乎处于静止状态。由于这一切发生在后台,所以许多没有耐心的用户开始认为服务器"挂"了,因而再次提交文件,这当然使得情况变得更糟糕。
为了尽可能使得文件上传感觉更友好些,一旦用户提交文件,许多站点将显示一个中间过程动画(例如一旋转图标)。尽管这一技术在上传提交到服务器时起一些作用,但它还是提供了太少的有关文件上传状态的信息。解决这个问题的另外一种尝试是实现一个applet——它通过FTP把文件上传到服务器。这一方案的缺点是:限制了你的用户,必须要有一个支持Java的浏览器。
在本文中,我们将实现一个具有AJAX能力的组件——它不仅实现把文件上传到服务器,而且"实时地"监视文件上传的实际过程。这个组件工作的四个阶段显示于下面的图1,2,3和4中:
图1.阶段1:选择文件上传
图2.阶段2:上传该文件到服务器
图3.阶段3:上传完成
图4.阶段4:文件上传摘要
二、 实现该组件
首先,我们分析创建多部分过滤的过程,它将允许我们处理并且监视文件上传。然后,我们将继续实现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");
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:谈select列表框
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash