AJAX和JSP实现的基于WEB的文件上传的进度控制代码

只为打酱油cc

只为打酱油cc

2016-02-19 12:26

图老师小编精心整理的AJAX和JSP实现的基于WEB的文件上传的进度控制代码希望大家喜欢,觉得好的亲们记得收藏起来哦!您的支持就是小编更新的动力~
1.引言 2.实现代码 2.1.服务器端代码 2.1.1. 文件上传状态类(FileUploadStatus) 2.1.2. 文件上传状态侦听类(FileUploadListener) 2.1.3. 后台服务类(BackGroundService) 2.1.4. 文件上传状态控制类(BeanControler) 2.2. 客户端代码 2.2.1. AjaxWrapper.js 2.2.2. fileUpload.html 2.2.3. result.jsp 2.2.4. fileUpload.css 2.3. 配置文件 3. 结语  1. 引言

   基于浏览器的文件上传,特别是对于通过input type="file"标签来实现上传的情况, 存在着严重的性能问题,因为用户提交了文件之后,在浏览器把文件上传到服务器的过程中,界面看上去似乎是静止的,如果是小文件还好些,如果不幸需要上传的是几兆、几十兆甚至上百兆的文件,我相信那是一种非常痛苦的体验,我们中间的很多人应该都有过此种不堪的经历。(一笑)

  现在我就针对这个问题给出一个解决方案,我们将实现一个具有监控能力的WEB上传的程序——它不仅把文件上传到服务器,而且"实时地"监视文件上传的实际过程。

解决方案的基本思路是这样的:

  在Form提交上传文件同时,使用AJAX周期性地从Servlet轮询上传状态信息   然后,根据此信息更新进度条和相关文字,及时反映文件传输状态   如果用户取消上传操作,则进行相应的现场清理工作:删除已经上传的文件,在Form提交页面中显示相关信息   如果上传完毕,显示已经上传的文件内容(或链接)

在介绍源代码之前,我们先来看看程序运行界面:

 2. 实现代码

   实现代码想当然的有服务器端代码和客户端代码(呵呵),我们先从服务器端开始。

 2.1. 服务器端代码  2.1.1. 文件上传状态类(FileUploadStatus)

   使用FileUploadStatus这个类记录文件上传状态,并将其作为服务器端与web客户端之间通信的媒介,通过对这个类对象提供上传状态作为服务器回应发送给web客户端, web客户端使用JavaScript获得文件上传状态。源代码如下:

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/)
/** * 本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。 * 如果需要转载本例程,请您注明作者。 * * 作者: 刘作晨 * EMail:liuzuochen@gmail.com */package liuzuochen.sample.upload;import java.util.*;public class FileUploadStatus {  //上传用户地址  private String uploadAddr;  //上传总量  private long uploadTotalSize = 0;  //读取上传总量  private long readTotalSize = 0;  //当前上传文件号  private int currentUploadFileNum = 0;  //成功读取上传文件数  private int successUploadFileCount = 0;  //状态  private String status = "";  //处理起始时间  private long processStartTime = 0l;  //处理终止时间  private long processEndTime = 0l;  //处理执行时间  private long processRunningTime = 0l;  //上传文件URL列表  private List uploadFileUrlList = new ArrayList();  //取消上传  private boolean cancel = false;  //上传base目录  private String baseDir = "";  public FileUploadStatus() {  }  public String getBaseDir() {return baseDir;  }  public void setBaseDir(String baseDir) {this.baseDir = baseDir;  }  public boolean getCancel() {return cancel;  }  public void setCancel(boolean cancel) {this.cancel = cancel;  }  public List getUploadFileUrlList() {return uploadFileUrlList;  }  public void setUploadFileUrlList(List uploadFileUrlList) {this.uploadFileUrlList = uploadFileUrlList;  }  public long getProcessRunningTime() {return processRunningTime;  }  public void setProcessRunningTime(long processRunningTime) {this.processRunningTime = processRunningTime;  }  public long getProcessEndTime() {return processEndTime;  }  public void setProcessEndTime(long processEndTime) {this.processEndTime = processEndTime;  }  public long getProcessStartTime() {return processStartTime;  }  public void setProcessStartTime(long processStartTime) {this.processStartTime = processStartTime;  }  public long getReadTotalSize() {return readTotalSize;  }  public void setReadTotalSize(long readTotalSize) {this.readTotalSize = readTotalSize;  }  public int getSuccessUploadFileCount() {return successUploadFileCount;  }  public void setSuccessUploadFileCount(int successUploadFileCount) {this.successUploadFileCount = successUploadFileCount;  }  public int getCurrentUploadFileNum() {return currentUploadFileNum;  }  public void setCurrentUploadFileNum(int currentUploadFileNum) {this.currentUploadFileNum = currentUploadFileNum;  }  public String getStatus() {return status;  }  public void setStatus(String status) {this.status = status;  }  public long getUploadTotalSize() {return uploadTotalSize;  }  public String getUploadAddr() {return uploadAddr;  }  public void setUploadTotalSize(long uploadTotalSize) {this.uploadTotalSize = uploadTotalSize;  }  public void setUploadAddr(String uploadAddr) {this.uploadAddr = uploadAddr;  }  public String toJSon() {StringBuffer strJSon = new StringBuffer();strJSon.append("{UploadTotalSize:").append(getUploadTotalSize()).append(",").append("ReadTotalSize:").append(getReadTotalSize()).append(",").append("CurrentUploadFileNum:").append(getCurrentUploadFileNum()).append(",").append("SuccessUploadFileCount:").append(getSuccessUploadFileCount()).append(",").append("Status:'").append(getStatus()).append("',").append("ProcessStartTime:").append(getProcessStartTime()).append(",").append("ProcessEndTime:").append(getProcessEndTime()).append(",").append("ProcessRunningTime:").append(getProcessRunningTime()).append(",").append("Cancel:").append(getCancel()).append("}");return strJSon.toString();  }}
  2.1.2. 文件上传状态侦听类(FileUploadListener)

   使用Common-FileUpload 1.2版本(20070103)。此版本提供了能够监视文件上传情况的ProcessListener接口,使开发者通过FileUploadBase类对象的setProcessListener方法植入自己的Listener。 FileUploadListener类实现了ProcessListener,在整个文件上传过程中,它对上传进度进行监控,并且根据上传 情况实时的更新上传状态Bean。源代码如下:

/** * 本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。 * 如果需要转载本例程,请您注明作者。 * * 作者: 刘作晨 * EMail:liuzuochen@gmail.com */package liuzuochen.sample.upload;import org.apache.commons.fileupload.ProgressListener;import javax.servlet.http.HttpServletRequest;public class FileUploadListener implements ProgressListener{private HttpServletRequest request=null;public FileUploadListener(HttpServletRequest request){this.request=request;}/** * 更新状态 */public void update(long pBytesRead, long pContentLength, int pItems){FileUploadStatus statusBean= BackGroundService.getStatusBean(request);statusBean.setUploadTotalSize(pContentLength);//读取完成  if (pContentLength == -1) {statusBean.setStatus("完成对" + pItems +"个文件的读取:读取了 " + pBytesRead + " bytes.");statusBean.setReadTotalSize(pBytesRead);statusBean.setSuccessUploadFileCount(pItems);statusBean.setProcessEndTime(System.currentTimeMillis());statusBean.setProcessRunningTime(statusBean.getProcessEndTime());  //读取中  } else {statusBean.setStatus("当前正在处理第" + pItems +"个文件:已经读取了 " + pBytesRead + 
"/" + pContentLength+ " bytes.");statusBean.setReadTotalSize(pBytesRead);statusBean.setCurrentUploadFileNum(pItems); statusBean.setProcessRunningTime(System.currentTimeMillis()); } BackGroundService.saveStatusBean(request,statusBean);}}
  2.1.3. 后台服务类(BackGroundService)

   BackGroundService这个Servlet类负责接收Form Post数据、回应状态轮询请求、处理取消文件上传的请求。 尽管可以把这些功能相互分离开来,但为了简单明了,还是将它们放到Servlet中,只是由不同的方法进行分割。 源代码如下:

/** * 本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。 * 如果需要转载本例程,请您注明作者。 * * 作者: 刘作晨 * EMail:liuzuochen@gmail.com */package liuzuochen.sample.upload;
/** * Title: 后台服务 * * Description: 为客户端提供上传及文件传输状态查询服务 * */import java.io.File;import java.io.IOException;import java.util.List;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.*;public class BackGroundService extends javax.servlet.http.HttpServlet implementsjavax.servlet.Servlet { public static final String UPLOAD_DIR = "/upload"; public static final String DEFAULT_UPLOAD_FAILURE_URL = "./result.jsp"; public BackGroundService() {super(); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doPost(request, response); } /** * 从文件路径中取出文件名 */ private String takeOutFileName(String filePath) {int pos = filePath.lastIndexOf(File.separator);if (pos 0) { return filePath.substring(pos + 1);} else { return filePath;} } /** * 从request中取出FileUploadStatus Bean */ public static FileUploadStatus getStatusBean( HttpServletRequest request) {BeanControler beanCtrl = BeanControler.getInstance();return beanCtrl.getUploadStatus(request.getRemoteAddr()); } /** * 把FileUploadStatus Bean保存到类控制器BeanControler */ public static void saveStatusBean( HttpServletRequest request, FileUploadStatus statusBean) {statusBean.setUploadAddr(request.getRemoteAddr());BeanControler beanCtrl = BeanControler.getInstance();beanCtrl.setUploadStatus(statusBean); } /** * 删除已经上传的文件 */ private void deleteUploadedFile(HttpServletRequest request) {FileUploadStatus satusBean = getStatusBean(request);for (int i = 0; i satusBean.getUploadFileUrlList().size(); i++) { File uploadedFile = new File(request.getRealPath(UPLOAD_DIR) + File.separator + satusBean.getUploadFileUrlList(). get(i)); uploadedFile.delete();}satusBean.getUploadFileUrlList().clear();satusBean.setStatus("删除已上传的文件");saveStatusBean(request, satusBean); } /** * 上传过程中出错处理 */ private void uploadExceptionHandle( HttpServletRequest request, String errMsg) throws ServletException, IOException {//首先删除已经上传的文件deleteUploadedFile(request);FileUploadStatus satusBean = getStatusBean(request);satusBean.setStatus(errMsg);saveStatusBean(request, satusBean); } /** * 初始化文件上传状态Bean */ private FileUploadStatus initStatusBean(HttpServletRequest request) {FileUploadStatus satusBean = new FileUploadStatus();satusBean.setStatus("正在准备处理");satusBean.setUploadTotalSize(request.getContentLength());satusBean.setProcessStartTime(System.currentTimeMillis());satusBean.setBaseDir(request.getContextPath() + UPLOAD_DIR);return satusBean; } /** * 处理文件上传 */ private void processFileUpload(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {DiskFileItemFactory factory = new DiskFileItemFactory();//设置内存缓冲区,超过后写入临时文件factory.setSizeThreshold(10240000);//设置临时文件存储位置factory.setRepository(new File(request.getRealPath("/upload/temp")));ServletFileUpload upload = new ServletFileUpload(factory);//设置单个文件的最大上传值upload.setFileSizeMax(102400000);//设置整个request的最大值upload.setSizeMax(102400000);upload.setProgressListener(new FileUploadListener(request));//保存初始化后的FileUploadStatus BeansaveStatusBean(request, initStatusBean(request));String forwardURL = "";try { List items = upload.parseRequest(request); //获得返回url for (int i = 0; i items.size(); i++) {FileItem item = (FileItem) items.get(i);if (item.isFormField()) { forwardURL = item.getString(); break;} } //处理文件上传 for (int i = 0; i items.size(); i++) {FileItem item = (FileItem) items.get(i);//取消上传if (getStatusBean(request).getCancel()) { deleteUploadedFile(request); break;}//保存文件else if (!item.isFormField() && item.getName().length() 0) { String fileName = takeOutFileName(item.getName()); File uploadedFile = new File(request.getRealPath(UPLOAD_DIR) + File.separator + fileName); item.write(uploadedFile); //更新上传文件列表 FileUploadStatus satusBean =getStatusBean(request); satusBean.getUploadFileUrlList().add(fileName); saveStatusBean(request, satusBean); Thread.sleep(500);} }} catch (FileUploadException e) { uploadExceptionHandle(request, "上传文件时发生错误:" + e.getMessage());} catch (Exception e) { uploadExceptionHandle(request, "保存上传文件时发生错误:" + e.getMessage());}if (forwardURL.length() == 0) { forwardURL = DEFAULT_UPLOAD_FAILURE_URL;}request.getRequestDispatcher(forwardURL).forward(request, response); } /** * 回应上传状态查询 */ private void responseStatusQuery(HttpServletRequest request, HttpServletResponse response) throws IOException {response.setContentType("text/xml");response.setHeader("Cache-Control", "no-cache");FileUploadStatus satusBean = getStatusBean(request);response.getWriter().write(satusBean.toJSon()); } /** * 处理取消文件上传 */ private void processCancelFileUpload(HttpServletRequest request, HttpServletResponse response) throws IOException {FileUploadStatus satusBean = getStatusBean(request);satusBean.setCancel(true);saveStatusBean(request, satusBean);responseStatusQuery(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {boolean isMultipart = ServletFileUpload.isMultipartContent(request);if (isMultipart) { processFileUpload(request, response);} else { request.setCharacterEncoding("UTF-8"); if (request.getParameter("uploadStatus") != null) {responseStatusQuery(request, response); } if (request.getParameter("cancelUpload") != null) {processCancelFileUpload(request, response); }} }}
  2.1.4. 文件上传状态控制类(BeanControler)

   这是一个单例类,它的功能是为客户端保存文件上传状态,这里我没有使用Session来存储文件上传状态,因为对于AJAX这种异步调用,服务器会开启不同的Session,所以无法通过Session保存文件上传状态。 我并不认为这种方法最好,如果有更好的方法,欢迎大家一起讨论。 源代码如下:

/** * 本例程演示了通过Web上传文件过程中的进度显示。您可以对本例程进行任何修改和使用。 * 如果需要转载本例程,请您注明作者。 * * 作者: 刘作晨 * EMail:liuzuochen@gmail.com */
package liuzuochen.sample.upload;/** * Title: 类控制器 * * Description: 主要作用是对FileUploadStatus进行管理,为客户端提供相应的 * FileUploadStatus类对象。这是一个单例类。 * */import java.util.Vector;public class BeanControler { private static BeanControler beanControler = new BeanControler(); private Vector vector = new Vector(); private BeanControler() { } public static BeanControler getInstance() {return beanControler; } /** * 取得相应FileUploadStatus类对象的存储位置 */ private int indexOf(String strID) {int nReturn = -1;for (int i = 0; i vector.size(); i++) { FileUploadStatus status = (FileUploadStatus) vector.elementAt(i); if (status.getUploadAddr().equals(strID)) {nReturn = i;break; }}return nReturn; } /** * 取得相应FileUploadStatus类对象 */ public FileUploadStatus getUploadStatus(String strID) {return (FileUploadStatus) vector.elementAt(indexOf(strID)); } /** * 存储FileUploadStatus类对象 */ public void setUploadStatus(FileUploadStatus status) {int nIndex = indexOf(status.getUploadAddr());if ( -1 == nIndex) { vector.add(status);} else { vector.insertElementAt(status, nIndex); vector.removeElementAt(nIndex + 1);} } /** * 删除FileUploadStatus类对象 */ public void removeUploadStatus(String strID){int nIndex = indexOf(strID);if(-1!=nIndex) vector.removeElementAt(nIndex); }}
 2.2. 客户端代码

   客户端我们采用Prototype框架。请下载。

  2.2.1. AjaxWrapper.js

   AjaxWrapper.js对Prototype进行了封装。请下载分析

  2.2.2. fileUpload.html

   fileUpload.html是文件上传界面。 请下载。

  2.2.3. result.jsp

   result.jsp是文件上传结果显示界面。 请下载

  2.2.4. fileUpload.css

   fileUpload.css是样式文件。 源代码如下:

body {
  color:#000;
  background-color:white;
  font:15px Georgia, "Lucida Grande", Arial, sans-serif;
  letter-spacing:0.01em;
  margin:15px;
}
#controlPanel,#resultPanel{
  width:700px;
  margin:20px auto;
  padding:25px;
  border:3px solid gray;
  -moz-border-radius:10px;
  background:#f8f8f8;
}
#errorArea{
   width:400px;
  margin:20px auto;
  padding:25px;
  border:3px solid gray;
  -moz-border-radius:10px;
  background:red;
}
#normalMessageArea{
  width:400px;
  margin:20px auto;
  padding:25px;
  border:3px solid gray;
  -moz-border-radius:10px;
  background:yellow;
}
#progressBar { padding-top: 5px; }
  #totalProgressBarBox {
   width: 350px;
   height: 20px;
   border: 1px inset;
   background: #eee;
}
#totalProgressBarBoxContent {
  width: 0;
  height: 20px;
  border-right: 1px solid #444;
  background: #9ACB34;
}

 2.3. 配置文件

   web.xml中完成Servlet的配置。

?xml version="1.0" encoding="UTF-8"?
web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
display-nameAjaxPractice/display-name
servlet
  description/description
  display-nameBackGroundService/display-name
  servlet-nameBackGroundService/servlet-name
  servlet-classliuzuochen.sample.upload.BackGroundService/servlet-class
/servlet

servlet-mapping
  servlet-nameBackGroundService/servlet-name
  url-pattern*.action/url-pattern
/servlet-mapping
welcome-file-list
  welcome-fileindex.html/welcome-file
   welcome-fileindex.htm/welcome-file
  welcome-fileindex.jsp/welcome-file
  welcome-filedefault.html/welcome-file
  welcome-filedefault.htm/welcome-file
  welcome-filedefault.jsp/welcome-file
/welcome-file-list
/web-app

(本文来源于图老师网站,更多请访问http://m.tulaoshi.com/webkaifa/) 3. 结语

   整个程序到这里就介绍完了,希望它多少能为您的工作或学习带来点儿帮助。

展开更多 50%)
分享

猜你喜欢

AJAX和JSP实现的基于WEB的文件上传的进度控制代码

Web开发
AJAX和JSP实现的基于WEB的文件上传的进度控制代码

基于PHP的AJAX技术实现文件异步上传

PHP
基于PHP的AJAX技术实现文件异步上传

s8lol主宰符文怎么配

英雄联盟 网络游戏
s8lol主宰符文怎么配

HTML5上传文件显示进度的实现代码

Web开发
HTML5上传文件显示进度的实现代码

掌控上传进度的AJAX Upload

Web开发
掌控上传进度的AJAX Upload

lol偷钱流符文搭配推荐

英雄联盟 网络游戏
lol偷钱流符文搭配推荐

基于AJAX的分页类实现代码

Web开发
基于AJAX的分页类实现代码

AJAX 进度条实现代码

Web开发
AJAX 进度条实现代码

lolAD刺客新符文搭配推荐

英雄联盟
lolAD刺客新符文搭配推荐

C#取鼠标点处颜色RGB

C#取鼠标点处颜色RGB

如何禁止键盘鼠标唤醒睡眠

如何禁止键盘鼠标唤醒睡眠
下拉加载更多内容 ↓