MyException - 我的异常网
当前位置:我的异常网» HTML/CSS » Servlet:htm+javascript+css+servlet (ajax)兑现

Servlet:htm+javascript+css+servlet (ajax)兑现上传(能显示进度条)

www.MyException.Cn  网友分享于:2015-08-26  浏览:20次
Servlet:htm+javascript+css+servlet (ajax)实现上传(能显示进度条)

本示例需要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;
	}

}

src/UploadListener.java,继承自ProgressListener,当使用commons_uploadfile组件上传时,调用组件类的方法可添加上传监听,组件就会不断调用UploadListener的update方法

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);
		
	}
}

src/UploadServlet.java,该类doPost方法用于处理上传,index.jsp后台会使用XmlHttpRequest调用本Servlet的doGet方法,从session中获取最新的上传数据情况

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();
    }

}



web.xml

<?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>

WebRoot / index.jsp

<%@ 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>




通过访问:http://127.0.0.1:8080/Test/   查看程序效果,如图

System.out.println打印的运行情况


至此,一个简单的上传程序就完成了。

文章评论

看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
每天工作4小时的程序员
每天工作4小时的程序员
程序员都该阅读的书
程序员都该阅读的书
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
我跳槽是因为他们的显示器更大
我跳槽是因为他们的显示器更大
初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
那些争议最大的编程观点
那些争议最大的编程观点
程序员应该关注的一些事儿
程序员应该关注的一些事儿
我是如何打败拖延症的
我是如何打败拖延症的
总结2014中国互联网十大段子
总结2014中国互联网十大段子
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
 程序员的样子
程序员的样子
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
写给自己也写给你 自己到底该何去何从
写给自己也写给你 自己到底该何去何从
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
代码女神横空出世
代码女神横空出世
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
Google伦敦新总部 犹如星级庄园
Google伦敦新总部 犹如星级庄园
老程序员的下场
老程序员的下场
程序员和编码员之间的区别
程序员和编码员之间的区别
一个程序员的时间管理
一个程序员的时间管理
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
要嫁就嫁程序猿—钱多话少死的早
要嫁就嫁程序猿—钱多话少死的早
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
编程语言是女人
编程语言是女人
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
2013年美国开发者薪资调查报告
2013年美国开发者薪资调查报告
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
我的丈夫是个程序员
我的丈夫是个程序员
鲜为人知的编程真相
鲜为人知的编程真相
中美印日四国程序员比较
中美印日四国程序员比较
10个调试和排错的小建议
10个调试和排错的小建议
漫画:程序员的工作
漫画:程序员的工作
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
程序员必看的十大电影
程序员必看的十大电影
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
为什么程序员都是夜猫子
为什么程序员都是夜猫子
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
旅行,写作,编程
旅行,写作,编程
2013年中国软件开发者薪资调查报告
2013年中国软件开发者薪资调查报告
如何成为一名黑客
如何成为一名黑客
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
Java 与 .NET 的平台发展之争
Java 与 .NET 的平台发展之争
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有