问题:实现文件上传并给出进度条显示上传过程信息。
- 如何实现上传的功能 ------使用apache的FileUpload组件上传文件
- 如何实现上传文件的监听功能 ------使用ProgressListener监听文件状态
- 如何实现记录上传状态的功能 ------使用session保存文件的状态
- 客户端如何状态的实时显示 -------客户端使用AJAX来查询上传的状态
思路:
客户端:界面的提交的时候使用<iframe 来实现模拟的无刷新提交,然后在使用ajax来周期的访问servlet并返回sesson中最新的状态信息。
服务器端:在servlet介绍到请求的时候,区分请求的类型是上传的请求还是ajax询问的请求,如果是上传的请求,则执行上传的方法,并启动监听保存上传状态到session中。
抽象出文件上传过程中需要用到的数据信息,文件的总大小、已上传大小、开始时间。
package com.test.entity;
public class Upload {
private long totalSize; //总大小
private long startTime = System.currentTimeMillis(); //开始时间
private long uploadSize; //已上传的大小
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
public long getStartTime() {
return startTime;
}
public void setStartTime(long startTime) {
this.startTime = startTime;
}
public long getUploadSize() {
return uploadSize;
}
public void setUploadSize(long uploadSize) {
this.uploadSize = uploadSize;
}
}
设置监听,实现接口ProgressListener
package com.test.lister;
import org.apache.commons.fileupload.ProgressListener;
import com.test.entity.Upload;
public class UploadLister implements ProgressListener{
<span > </span>private Upload upload = null;
<span > </span>public UploadLister(Upload upload){
<span > </span>this.upload = upload;
<span > </span>}
<span > </span>/**
<span > </span> * @param uploadSize 已上传大小
<span > </span> * @param totalSize 总大小
<span > </span> * @param items 上传第几个(暂时用不到)
<span > </span> */
<span > </span>public void update(long uploadSize,long totalSize,int items) {
<span > </span>upload.setUploadSize(uploadSize);
<span > </span>upload.setTotalSize(totalSize);
<span > </span>}
}
上传服务的servlet:
package com.test.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
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.ServletFileUpload;
import com.test.lister.UploadLister;
@SuppressWarnings("serial")
public class Upload extends HttpServlet {
public Upload() {
super();
}
public void destroy() {
super.destroy();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
com.test.entity.Upload upload = new com.test.entity.Upload();
UploadLister lister = new UploadLister(upload);
ServletFileUpload servletFileUpload = new ServletFileUpload(
new DiskFileItemFactory());
// 设置上传监听器
servletFileUpload.setProgressListener(lister);
//使用session保存文件的状态
request.getSession().setAttribute("upload", upload);
List list = null;
try {
list = servletFileUpload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
for (Iterator iter = list.iterator(); iter.hasNext();) {
// 得到文件对象
FileItem fileItem = (FileItem) iter.next();
// 是表单才进行处理
if (fileItem.isFormField()) {
break;
}
// 同一linux和windows的路径分隔符
String name = fileItem.getName().replaceAll("/", "\\");
// 得到文件名
int index = name.lastIndexOf("\\");
String fileFileName = "";
if (index == -1) {
fileFileName = name;
} else {
fileFileName = name.substring(index + 1);
}
InputStream fileInputStream = fileItem.getInputStream();
String path = request.getRealPath("/upload");
// 也可不用自己写实现方法直接使用,fileItem.write(uploadFile);
File uploadFile = new File(path, fileFileName);
// 首先要确认路径是否存在
uploadFile.getParentFile().mkdirs();
// 检查文件是否已经存在
if (!uploadFile.exists()) {
// 建立文件
uploadFile.createNewFile();
}
FileOutputStream out2 = new FileOutputStream(uploadFile);
// 开始copy文件
@SuppressWarnings("unused")
int len = 0;// 每次读取的字节数
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes, 0, bytes.length)) != -1) {
out2.write(bytes);
}
out2.flush();
out2.close();
fileInputStream.close();
}
out.flush();
out.close();
}
public void init() throws ServletException {
}
}
刷新进度信息的servlet
package com.test.servlet;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
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.ServletFileUpload;
import com.test.lister.UploadLister;
@SuppressWarnings("serial")
public class Upload extends HttpServlet {
public Upload() {
super();
}
public void destroy() {
super.destroy();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
com.test.entity.Upload upload = new com.test.entity.Upload();
UploadLister lister = new UploadLister(upload);
ServletFileUpload servletFileUpload = new ServletFileUpload(
new DiskFileItemFactory());
// 设置上传监听器
servletFileUpload.setProgressListener(lister);
//使用session保存文件的状态
request.getSession().setAttribute("upload", upload);
List list = null;
try {
list = servletFileUpload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
}
for (Iterator iter = list.iterator(); iter.hasNext();) {
// 得到文件对象
FileItem fileItem = (FileItem) iter.next();
// 是表单才进行处理
if (fileItem.isFormField()) {
break;
}
// 同一linux和windows的路径分隔符
String name = fileItem.getName().replaceAll("/", "\\");
// 得到文件名
int index = name.lastIndexOf("\\");
String fileFileName = "";
if (index == -1) {
fileFileName = name;
} else {
fileFileName = name.substring(index + 1);
}
InputStream fileInputStream = fileItem.getInputStream();
String path = request.getRealPath("/upload");
// 也可不用自己写实现方法直接使用,fileItem.write(uploadFile);
File uploadFile = new File(path, fileFileName);
// 首先要确认路径是否存在
uploadFile.getParentFile().mkdirs();
// 检查文件是否已经存在
if (!uploadFile.exists()) {
// 建立文件
uploadFile.createNewFile();
}
FileOutputStream out2 = new FileOutputStream(uploadFile);
// 开始copy文件
@SuppressWarnings("unused")
int len = 0;// 每次读取的字节数
byte[] bytes = new byte[1024];
while ((len = fileInputStream.read(bytes, 0, bytes.length)) != -1) {
out2.write(bytes);
}
out2.flush();
out2.close();
fileInputStream.close();
}
out.flush();
out.close();
}
public void init() throws ServletException {
}
}
上传的文件的jsp界面
<html>
<head>
<base href="<%=basePath%>">
<title>使用Ajax、Jquery进行文件上传,带进度条</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="struts2 ajax upload progress">
<meta http-equiv="description" content="file upload by struts2 and ajax and jquery progress">
<script type="text/javascript" src="js/jquery-1.7.1.js"></script>
<script type="text/javascript">
var over = false;
var inter;
function upload(){
over = false;
$("#state").html("");
$("#progress").css("width","0");
$("input[type=submit]").attr("disabled",true);
$("#progress").css("width","0%");
$("#state").html("正在上传... 总大小:0MB,已上传:0MB,0%,已用时:0秒,剩余时间:0秒,速度:0KB/S");
inter = setInterval(req,1000);
}
function req(){
//如果上传已经完成
if(over){
clearInterval(inter);
return;
}
var url = "upload/AjaxServlet";
$.get(url,function(date){
var state = date.split("-");
$("#state").html("正在上传... 总大小:"+state[4]+"MB,已上传:"+state[3]+"MB,"+state[2]+"%,已用时:"+state[0]+"秒,剩余时间:"+state[5]+"秒,速度:"+state[1]+"KB/S");
$("#progress").animate({width:state[2]+"%"},500);
if(state[3] == state[4]){
over = true;
$("input[type=submit]").attr("disabled",false);
$("#state").html("上传已完成,总大小:"+state[4]+"MB,已上传:"+state[3]+"MB,"+state[2]+"%,已用时:"+state[0]+"秒,剩余时间:"+state[5]+"秒,速度:"+state[1]+"KB/S");
}
});
}
</script>
</head>
<body>
<form action="servlet/Upload" method="post" enctype="multipart/form-data" target="upload_iframe" οnsubmit="upload()">
<p><input type="file" name="file" id="file"></p>
<p><input type="submit" value="上传文件"></p>
</form>
<iframe name="upload_iframe" width="0" height="0" frameborder="0"></iframe>
<div id="state">
</div>
<div id="progress" style="background: #728820; height: 20px; width: 0">
</div>
</body>
</html>
配置文件信息
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
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_2_5.xsd">
<servlet>
<servlet-name>AjaxServlet</servlet-name>
<servlet-class>com.test.servlet.AjaxServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>Upload</servlet-name>
<servlet-class>com.test.servlet.Upload</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>AjaxServlet</servlet-name>
<url-pattern>/upload/AjaxServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Upload</servlet-name>
<url-pattern>/servlet/Upload</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>upload.jsp</welcome-file>
</welcome-file-list>
</web-app>
用到的公共文件:
jquery-1.7.1.js 、
commons-fileupload-1.2.2.jar、
commons-io-2.0.1.jar