本示例需要commons-fileupload-1.3.jar和commons-io-2.4.jar的支持,新手请参阅无进度条的上传
http://blog.csdn.net/tabactivity/article/details/11180631
确认您的环境配置成功后,下面开始编码:
src/UploadStatus.java ,数据模型类
package com.xieyuan; public class UploadStatus { private long bytesRead; private long contentLength; private int items; private long startTime = System.currentTimeMillis(); public long getBytesRead() { return bytesRead; } public void setBytesRead(long bytesRead) { this.bytesRead = bytesRead; } public long getContentLength() { return contentLength; } public void setContentLength(long contentLength) { this.contentLength = contentLength; } public int getItems() { return items; } public void setItems(int items) { this.items = items; } public long getStartTime() { return startTime; } public void setStartTime(long startTime) { this.startTime = startTime; } }
package com.xieyuan; import org.apache.commons.fileupload.ProgressListener; public class UploadListener implements ProgressListener { private UploadStatus status; public UploadListener(UploadStatus status) { this.status = status; } public void update(long bytesRead, long contentLength, int items) { status.setBytesRead(bytesRead); status.setContentLength(contentLength); status.setItems(items); } }
package com.xieyuan; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sound.sampled.AudioFormat.Encoding; import org.apache.commons.fileupload.DiskFileUpload; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; public class UploadServlet extends HttpServlet { //定义临时文件盒上传文件的存储路径 private File uploadTemp=null; private File uploadPath=null; /** * Constructor of the object. */ public UploadServlet() { super(); } /** * Destruction of the servlet. <br> */ public void destroy() { super.destroy(); // Just puts "destroy" string in log // Put your code here } /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //禁用缓存,index.jsp后台会使用XmlHttpRequest调用本Servlet的doGet方法,从session中获取最新的上传数据情况 response.setHeader("Cache-Control", "no-store"); response.setHeader("Pragrma", "no-cache"); response.setDateHeader("Expires", 0); response.setContentType("text/html;charset=utf-8"); UploadStatus status = (UploadStatus) request.getSession(true) .getAttribute("uploadStatus"); if (status == null) { response.getWriter().println("没有上传信息"); return; } long startTime = status.getStartTime(); long currentTime = System.currentTimeMillis(); // 已传输的时间 单位:s long time = (currentTime - startTime) / 1000 + 1; // 传输速度 单位:byte/s double velocity = ((double) status.getBytesRead()) / (double) time; // 估计总时间 单位:s double totalTime = status.getContentLength() / velocity; // 估计剩余时间 单位:s double timeLeft = totalTime - time; // 已完成的百分比 int percent = (int) (100 * (double) status.getBytesRead() / (double) status .getContentLength()); // 已完成数 单位:M double length = ((double) status.getBytesRead()) / 1024 / 1024; // 总长度 单位:M double totalLength = ((double) status.getContentLength()) / 1024 / 1024; // 格式:百分比||已完成数(M)||文件总长度(M)||传输速率(K)||已用时间(s)||估计总时间(s)||估计剩余时间(s)||正在上传第几个文件 String value = percent + "||" + length + "||" + totalLength + "||" + velocity + "||" + time + "||" + totalTime + "||" + timeLeft + "||" + status.getItems(); response.getWriter().println(value); } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { File file=null; String description=null; //设置响应格式(不设置请求格式,因为文件是二进制的,不能使用UTF-8格式化请求数据) response.setContentType("text/html;charset=utf-8"); PrintWriter out=response.getWriter(); out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">"); out.println("<HTML>"); out.println("<HEAD><TITLE>文件上传</TITLE></HEAD>"); out.println("<BODY style='margin:50px'>"); out.println("上传日志:<BR/>"); UploadStatus status=new UploadStatus(); UploadListener listener=new UploadListener(status); /* * * 把 UploadStatus 放到 session 里,引用 返回与此请求关联的当前HttpSession,如果没有当前会话和创造是真实的,返回一个新的会话。 如果创建是假的,并要求有没有有效的HttpSession,这个方法返回null。 */ request.getSession(true).setAttribute("uploadStatus", status); //创建基于磁盘的工厂,针对大文件,临时文件将存储在磁盘 DiskFileItemFactory factory=new DiskFileItemFactory(); //设置缓冲区大小,超出该文件直接写入到磁盘的大小设置门槛。 factory.setSizeThreshold(10240); //这里默认10KB //设置用于大于配置的大小阈值设置的临时存储文件目录。 factory.setRepository(uploadTemp); //创建一个文件上传的句柄 ServletFileUpload upload=new ServletFileUpload(factory); //设置最大文件尺寸 ,这里是40MB upload.setSizeMax(41943040); upload.setHeaderEncoding("utf-8"); // 设置 listener upload.setProgressListener(listener); try { //将解析结果放在LIST中 List<FileItem> list =upload.parseRequest(request); out.println("遍历所有的 FileItem ... <br/>"); // 遍历 list 中所有的 FileItem for(FileItem item:list) { // 如果是 文本域 if(item.isFormField()) { if(item.getFieldName().equals("description1")||item.getFieldName().equals("description2")) { description = item.getString("UTF-8"); System.out.println("遍历到 "+item.getFieldName()+" ... <br/>"+description+"<BR/>"); } } else { //否则为文件域,当getName为Null说明没有选则文件 if((item.getFieldName().equals("file1")||item.getFieldName().equals("file2")) &&item.getName()!=null&&!item.getName().equals("")) { try { // 统一 Linux 与 windows 的路径分隔符 String fileName = item.getName(); //fileName = fileName.substring(fileName.lastIndexOf("\\")); // 服务器端文件,放在 upload 文件夹下 file=new File(uploadPath,fileName); if(!file.getParentFile().exists()) file.getParentFile().mkdirs(); if(!file.exists()) file.createNewFile(); item.write(file); System.out.println("遍历到 "+fileName+" ... <br/>"+description+"<BR/>"); } catch (Exception e) { System.out.println("Request 上传失败!"+e.getMessage()); } finally //总是立即删除保存表单字段内容的临时文件 { item.delete(); } } } } System.out.println("Request 解析完毕,文件上传完毕!"); } catch (Exception e) { System.out.println("Request 解析异常!"+e.getMessage()); } out.flush(); out.close(); } /** * Initialization of the servlet. <br> * * @throws ServletException if an error occurs */ public void init() throws ServletException { uploadPath=new File(this.getServletContext().getRealPath("upload")); if(!uploadPath.exists()) uploadPath.mkdirs(); uploadTemp=new File(this.getServletContext().getRealPath("upload/temp")); if(!uploadTemp.exists()) uploadTemp.mkdirs(); } }
<?xml version="1.0" encoding="UTF-8"?> <web-app 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"> <servlet> <description>This is the description of my J2EE component</description> <display-name>This is the display name of my J2EE component</display-name> <servlet-name>UploadServlet</servlet-name> <servlet-class>com.xieyuan.UploadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>UploadServlet</servlet-name> <url-pattern>/servlet/UploadServlet</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <title>带进度条的文件上传</title> <style type="text/css"> #progressBar{width:400px;height:12px;background:#FFFFFF;border:1px solid #000000;padding:1px;} #progressBarItem{width:30%;height:100%;background:#FF0000;} </style> <script type="text/JavaScript"> <!--默认为已经完成上传操作--> var _finished=true; function $(obj) { return document.getElementById(obj); } <!--显示进度条等信息--> function showStatus() { _finished=false; $('status').style.display='block'; $('progressBarItem').style.width='1%'; $('btnSubmit').disabled=true; <!--隔1秒后执行一次--> setTimeout("requestStatus()",1000); } <!--发送请求获取文件上传状态--> function requestStatus() { if(_finished) return; var req=createRequest(); req.open("GET","servlet/UploadServlet"); req.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); req.onreadystatechange=function(){callback(req);}; //我们的实例在 open() 的第三个参数中使用了 "true"。该参数规定请求是否异步处理。 //True 表示脚本会在 send() 方法之后继续执行,而不等待来自服务器的响应。 req.send(null); setTimeout("requestStatus()",1000); } function createRequest() { if(window.XMLHttpRequest)//ns { return new XMLHttpRequest(); }else//IE { try{ return new ActiveXObject("Msxml2.XMLHTTP"); }catch(e){ return new ActiveXObject("Microsoft.XMLHTTP"); } } return null; } function callback(req) { //请求结束后 if(req.readyState==4) { //如果发生错误,则显示错误信息 if(req.status!=200) { _debug("发生错误。 req.status: " + req.status + ""); return; } var ss = req.responseText.split("||"); // 格式:百分比||已完成数(M)||文件总长度(M)||传输速率(K)||已用时间(s)||估计总时间(s)||估计剩余时间(s)||正在上传第几个文件 $('progressBarItem').style.width = '' + ss[0] + '%'; $('statusInfo').innerHTML = '已完成百分比: ' + ss[0] + '% <br />已完成数(M): ' + ss[1] + '<br/>文件总长度(M): ' + ss[2] + '<br/>传输速率(K): ' + ss[3] + '<br/>已用时间(s): ' + ss[4] + '<br/>估计总时间(s): ' + ss[5] + '<br/>估计剩余时间(s): ' + ss[6] + '<br/>正在上传第几个文件: ' + ss[7]; if(ss[1] == ss[2]) { _finished = true; $('statusInfo').innerHTML += "<br/><br/><br/>上传已完成。"; $('btnSubmit').disabled = false; } _debug("status.jsp 返回值:" + req.responseText); } } function _debug(obj) { //var div=document.createElement("DIV"); $('debug').innerHTML="[debug]:"+obj+"<br/>"; //document.body.appendChild(div); } </script> </head> <body style="margin:50px"> <iframe name="upload_iframe" width="0" height="0" frameborder="0" ></iframe> <form action="servlet/UploadServlet" method="post" enctype="multipart/form-data" target="upload_iframe" onsubmit="showStatus();"> <p>上传文件:</p> 文件1:<input type="file" name="file1" /><br/> 描述:<input type="text" name="description1" /><br/> 文件2:<input type="file" name="file2" /><br/> 描述:<input type="text" name="description2" /><br/> <input type="submit" id="btnSubmit" value=" 上 传 " /> </form> <div id="status" style="display:none;position:relative;line-height:100%;opacity:1;"> 上传进度: <div id="progressBar" ><div id="progressBarItem" /></div> <div id="statusInfo" style="margin:10px 0px 0px 0px;"/> </div> <BR/> <div id="debug" /> </body> </html>
System.out.println打印的运行情况
至此,一个简单的上传程序就完成了。