首页 > 代码库 > ajax文件上传进度条

ajax文件上传进度条

写在前面:
思路:首先将表单提交servlet,servlet中做文件上传处理,上传的参数封装成对象存入session中,提交到的页面为隐藏的iframe窗口。然后使用ajax异步请求获取session中的对象,并将对象转换成json对象输出出来。当对象状态为上传完成或操作异常时将session中对应的属性清除掉。异步操作的回调函数可以使用
var jinduStatus = eval("("+xmlHttp.responseText+")") 的方法将json转换为对象,再通过jinduStatus["xxx"]或jinduStatus.xxx的形式获取对应json中的参数值。回调函数再根据服务端返回过来的参数值判断是否继续调用异步函数。
细节考虑:
易忽略点: 
A)页面中有多个文件上传控件,但提交的时候没有全部填写
B)文件上传的过程中关闭了当前页面,但是session仍存在。 
 一、所需jar包:
commons-fileupload-x.x.x.jar
commons-io-x.x.jar
二、上传页面:test01.jsp
 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>进度条演示实例1(用xmlHttpRequest对象异步处理)</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<script type="text/javascript" src=http://www.mamicode.com/"js/xmlHttp.js"></script>
</head>
<body>
<div id="fullJindu" style="width: 500px;border: 1px solid;">
<div id="upPercent" style="width: 500px;position: absolute;text-align: center"></div>
<div id="jindu" style="background-color: #ff00ff;width: 0px"></div>
</div>
<div id="showJindu"></div>
<br/>
<iframe name="uploadToPage" style="display: none"></iframe>
<form action="servlet/FileUpload" id="upFileForm" method="post" enctype="multipart/form-data" target="uploadToPage">
<input type="file" id="file" name="file"/><br/>
<input type="file" id="file" name="file"/><br/>
<button id="upFileBtn" onclick="uploadFileListener()">上传</button>
</form>
</body>
</html>
三、请求上传:js/xmlHttp.js
 var xmlHttp = false;
function createXMLHTTPRequest(){
try{
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}catch(ee){
xmlHttp = new XMLHttpRequest();
}
}
return xmlHttp;
}
function uploadFileListener(){
var upFileForm = document.getElementById("upFileForm");
var files = document.getElementsByName("file");
var empSelectFile = true;
for(var i=0;i<files.length;i++){
if(files[i].value != ‘‘){
empSelectFile = false;
}
}
if(empSelectFile){
alert(‘请上传文件‘+empSelectFile);
return;
}else{
upFileForm.submit();
document.getElementById("upFileBtn").disabled = ‘disabled‘;
uploadFile();
}
}
var requestCount = 0;
function uploadFile(){
xmlHttp = createXMLHTTPRequest();
xmlHttp.open("post","servlet/FileUpload?reading=running&requestCount="+(++requestCount),true);
xmlHttp.onreadystatechange = uploadFileOnServer;
xmlHttp.send(null);
uploadFileOnServer();
}
function uploadFileOnServer(){
if(xmlHttp.readyState == 4){
if(xmlHttp.status == 200){
var json = xmlHttp.responseText;
if(json){
var jinduStatus = eval("("+xmlHttp.responseText+")");
//alert(jinduStatus);
var showFlag = jinduStatus["showFlag"];
//alert(showFlag);
var showJindu = document.getElementById("showJindu");
showJindu.innerHTML = jinduStatus["retMsg"];
changeJindu(jinduStatus["totalPercent"]);
if(showFlag == ‘0‘){
uploadFile();
}else{
alert("文件上传成功");
document.getElementById("upFileBtn").disabled = ‘‘;
}
}else{
uploadFile();
}
}
}
}

function changeJindu(percent){
var upPercent = document.getElementById("upPercent");
upPercent.innerHTML = percent+"%";
var fullJinduWidth = document.getElementById("fullJindu").style.width;
var jinduNode = document.getElementById("jindu");
var fullJinduVal = parseInt(fullJinduWidth.substring(0,fullJinduWidth.length-2));
jinduNode.style.width = (fullJinduVal*percent/100)+‘px‘;
}

function testProgress(){
var jindu = document.getElementById("jindu");
var jinduWidth = jindu.style.width;
var jinduWidthVal = jinduWidth.substring(0,jinduWidth.length-2);
jindu.style.width = parseInt(jinduWidthVal)+5;
}

四、上传处理servlet:FileUpload.java
 package com.wtb.test.ajax.xmlHttp.progress;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
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.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

@SuppressWarnings("serial")
public class FileUpload extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
HttpSession session = request.getSession();
PrintWriter out = response.getWriter();
if("running".equals(request.getParameter("reading"))){
Status status = (Status) session.getAttribute("statusSession");
if("1".equals(request.getParameter("requestCount"))){//第一次请求
if(status!=null){
if(status.getShowFlag() == 1){
session.removeAttribute("statusSession");
}
}
}else{
if(status!=null){
if(status.getShowFlag() == 1){
session.removeAttribute("statusSession");
}
}
}
if(status == null){
status = new Status();
}
out.print(status.toJson());
out.close();
}else{//上传文件
//创建文件项目工厂对象
FileItemFactory factory = new DiskFileItemFactory();
//用工厂实例化上传组件,ServletFileUpload解析文件上传请求
ServletFileUpload upload = new ServletFileUpload(factory);
//创建进度状态对象
Status status = new Status();
try {
session.setAttribute("upFileFinish", "0");
//将解析结果放入List中
List<FileItem> fileItemList = upload.parseRequest(request);
status.setRetMsg("计算文件大小...");
session.setAttribute("statusSession", status);
//计算要上传的文件的总大小,将其放入到状态对象中。
long totalSize = 0;
for(FileItem fileItem:fileItemList){
if(!fileItem.isFormField()){//文件域
totalSize += fileItem.getSize();
}
}
status.setTotalSize(totalSize);
status.setRetMsg("文件总大小为:"+totalSize+"字节,开始上传文件...");
String totalPercent = "0.00";
status.setTotalPercent("0.00");
status.setFilePercent("0.00");
System.out.println(status.getRetMsg());
session.setAttribute("statusSession", status);
long totalWriteSize = 0;
for(FileItem fileItem:fileItemList){
if(fileItem.isFormField()){//文本域
//获取表单名称即<input name="xxx" .../>中name属性的值,此方法同样适用于文件域
String fieldName = fileItem.getFieldName();
String value = http://www.mamicode.com/fileItem.getString();//获取文本域内容,此方法对文件域不适用
System.out.println(fieldName+":"+value);
}else{//文件域
//获取上传文件名
String filePath = fileItem.getName();
if(!"".equals(filePath)){
String fileName = filePath.substring(filePath.lastIndexOf("\\")+1);
//获取文件数据输入流
InputStream in = fileItem.getInputStream();
//设置文件上传路径
String upFileDir = this.getServletContext().getRealPath("/uploadFile");
//设置进度状态
long fileSize = fileItem.getSize();
status.setFileSize(fileSize);
status.setContextType(fileItem.getContentType());
status.setState(1);
status.setShowFlag(0);
//创建文件输出流,将文件写入到该输出流中
FileOutputStream fos = new FileOutputStream(new File(upFileDir,fileName));
byte[] b = new byte[1024];
int len = 0;
long fileWriteSize = 0;
String filePercent = "0.00";
while((len=in.read(b))!=-1){
fos.write(b, 0, len);
totalWriteSize += len;
fileWriteSize += len;
status.setTotalWriteSize(totalWriteSize);
status.setFileWriteSize(fileWriteSize);
filePercent = String.format("%.2f", ((double)fileWriteSize)*100/fileSize);
totalPercent = String.format("%.2f", ((double)totalWriteSize)*100/totalSize);
status.setFilePercent(filePercent);
status.setTotalPercent(totalPercent);
status.setRetMsg("正在上传"+fileName+";单个文件进度:"+filePercent
+"%;整体进度:"+totalPercent+"%.");
//System.out.println(status.getRetMsg());
session.setAttribute("statusSession", status);
}
in.close();
fos.close();
}
}
}
status.setState(2);
status.setRetMsg("文件上传成功");
status.setShowFlag(1);
System.out.println(status.getRetMsg());
session.setAttribute("statusSession", status);
} catch (Exception e) {
e.printStackTrace();
status.setState(3);
status.setRetMsg("文件上传出现异常");
status.setShowFlag(1);
session.setAttribute("statusSession", status);
}
}
}

}

五、servlet对应web.xml文件:
 <?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ;
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<servlet>
<servlet-name>FileUpload</servlet-name>
<servlet-class>com.wtb.test.ajax.xmlHttp.progress.FileUpload</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>FileUpload</servlet-name>
<url-pattern>/servlet/FileUpload</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
六、文件上传状态:Status.java
 package com.wtb.test.ajax.xmlHttp.progress;

public class Status {
private long totalSize;//上传文件总大小
private long fileSize;//当前文件大小
private long totalWriteSize;//总写入字节
private long fileWriteSize;//当前文件写入字节
private int state;//当前状态:0:未上传;1:上传中;2:上传结束;3:上传时遇到异常。
private String retMsg;//描述
private int showFlag;//是否继续读取进度。0:读取进度;1:终止上传操作
private String contextType;//当前文件类型
private String filePercent;//单个文件上传的百分比
private String totalPercent;//总上传百分比
public Status(){
setRetMsg("");
setContextType("");
setFilePercent("0.00");
setTotalPercent("0.00");
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
public long getFileSize() {
return fileSize;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public long getTotalWriteSize() {
return totalWriteSize;
}
public void setTotalWriteSize(long totalWriteSize) {
this.totalWriteSize = totalWriteSize;
}
public long getFileWriteSize() {
return fileWriteSize;
}
public void setFileWriteSize(long fileWriteSize) {
this.fileWriteSize = fileWriteSize;
}
public int getState() {
return state;
}
public void setState(int state) {
this.state = state;
}
public String getRetMsg() {
return retMsg;
}
public void setRetMsg(String retMsg) {
this.retMsg = retMsg;
}
public int getShowFlag() {
return showFlag;
}
public void setShowFlag(int showFlag) {
this.showFlag = showFlag;
}
public String getContextType() {
return contextType;
}
public void setContextType(String contextType) {
this.contextType = contextType;
}
public String getFilePercent() {
return filePercent;
}
public void setFilePercent(String filePercent) {
this.filePercent = filePercent;
}
public String getTotalPercent() {
return totalPercent;
}
public void setTotalPercent(String totalPercent) {
this.totalPercent = totalPercent;
}
public String toJson(){
return "{\"totalSize\":\""+totalSize+"\",\"fileSize\":\""+fileSize
+"\",\"totalWriteSize\":\""+totalWriteSize+"\","+"\"fileWriteSize\":\""+fileWriteSize
+"\",\"state\":\""+state+"\",\"retMsg\":\""+retMsg
+"\",\"showFlag\":\""+showFlag+"\",\"contextType\":\""+contextType
+"\",\"filePercent\":\""+filePercent+"\",\"totalPercent\":\""+totalPercent+"\"}";
}
}
七、在WebRoot目录下新建一个uploadFile文件夹,用于存放上传的文件。

==================================================================================

如果导入JQuery文件,jsp页面及js页面如下,其他页面不需修改。
实现页面如下:
一、将jquery-1.9.1.js文件放在WebRoot/js目录下。
二、页面展示(test02.jsp):(与test01.jsp相比就是将引入jquery文件并把js/xmlHttp.js修改为js/jqAjax.js)
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>进度条演示实例2(用JQuery异步处理)</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<script type="text/javascript" src=http://www.mamicode.com/"js/jquery-1.9.1.js"></script>
<script type="text/javascript" src=http://www.mamicode.com/"js/jqAjax.js"></script>
</head>
<body>
<div id="fullJindu" style="width: 500px;border: 1px solid;">
<div id="upPercent" style="width: 500px;position: absolute;text-align: center"></div>
<div id="jindu" style="background-color: #ff00ff;width: 0px"></div>
</div>
<div id="showJindu"></div>
<br/>
<iframe name="uploadToPage" style="display: none"></iframe>
<form action="servlet/FileUpload" id="upFileForm" method="post" enctype="multipart/form-data" target="uploadToPage">
<input type="file" name="file"/><br/>
<input type="file" name="file"/><br/>
<button id="upFileBtn" onclick="uploadFileListener()">上传</button>
</form>
</body>
</html>
三、js/jqAjax.js
function uploadFileListener(){
var files = $("input[type=‘file‘]");
var emp = true;
for(var i=0;i<files.size();i++){
if(files[i].value!=‘‘){
emp = false;
}
}
if(emp){
alert("请上传文件");
}else{
$("#upFileForm").submit();
$("#upFileBtn").attr(‘disabled‘,true);
ajaxFun();
}
}
var requestCount = 0;
function ajaxFun(){
//使用$.post(url,[data],[callback],[type])方式进行异步操作
/**
$.post("servlet/FileUpload",{"reading":"running","requestCount":(++requestCount)},function(status){
if(status){
$("#showJindu").html(status.retMsg);
changeProgress(status.totalPercent);
if(status.showFlag == ‘0‘){
window.setTimeout(function(){
ajaxFun();
}, 100);
}else{
//稍等一点点时间让进度条修改完进度
window.setTimeout(function(){
alert(status.retMsg);
$("#upFileBtn").attr(‘disabled‘,false);
}, 100);
}
}else{
window.setTimeout(function(){
ajaxFun();
}, 100);
}
},"json");
*/
//使用$.ajax({url,[settings]})进行异步操作
$.ajax({
type:"post",
url:"servlet/FileUpload",
data:"reading=running&requestCount="+(++requestCount),
success:function(retData){
if(retData){
var status = eval("("+retData+")");
$("#showJindu").html(status["retMsg"]);
changeProgress(status["totalPercent"]);
if(status["showFlag"] == ‘0‘){
window.setTimeout(function(){
ajaxFun();
}, 100);
}else{
//稍等一点点时间让进度条修改完进度
window.setTimeout(function(){
alert(status["retMsg"]);
$("#upFileBtn").attr(‘disabled‘,false);
}, 100);
}
}else{
window.setTimeout(function(){
ajaxFun();
}, 100);
}
}
});
}

function changeProgress(percent){
$("#upPercent").html(percent+"%");
$("#jindu").css({
"width":($("#fullJindu").width()*percent/100)+"px"
});
}
 

 


图片



ajax文件上传进度条