后台:
package com.scott.uploadfile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
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.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* @author scott.wanglei
* @since 2009-1-8
* 使用多线程实现文件进度的显示
*/
public class UploadFile extends HttpServlet {
private static final long serialVersionUID = 4030816613803833495L;
//同步散列表保存文件上传进度类的引用
private ConcurrentHashMap<String,Progress> chp = new ConcurrentHashMap<String,Progress>();
public UploadFile() {
super();
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
this.doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.setHeader("pragma", "no-cache");
response.setHeader("cache-control", "no-cache");
response.setHeader("expires", "0");
if(request.getContentType() == null){
Progress p = new Progress();
//根据上request对象产生的String的hashcode值做为key值
String key = Integer.toString(request.toString().hashCode());
//根据key值储存当前文件的进度对象引用
chp.put(key, p);
//把key传回并发起上传文件的请求
this.sendMsg(response,"parent.uploadFile('"+key+"')");
//上传线程没有开始时候阻塞更新线程
while(true){
if(p.getLength() != 0)
break;
}
long temp = 0;
while(! p.isComplete){
if(temp != p.getCurrentLength()){
temp = p.getCurrentLength();
//更新客户端进度
this.sendMsg(response, "parent.upload('"+temp+"','"+p.getLength()+"')");
}
}
}
else if(request.getContentType().indexOf("multipart/form-data") > -1){
//上传线程开始执行
String key = request.getParameter("key");
Progress p = chp.get(key);
if(p != null){
p.setLength(request.getContentLength());
this.startUploadFile(request,response, p,request.getRealPath("/"),key);
chp.remove(key);
}
else{
this.sendMsg(response, "alert('Progress is null,k1 is not equal k2')");
}
}
else {
this.sendMsg(response, "alert('ContentType is not correctly')");
}
}
//上传文件
private void startUploadFile( HttpServletRequest request, HttpServletResponse response,Progress p,
String path,String key)
throws IOException{
//设置上传工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setRepository(new File(path));
//阀值,超过这个值才会写到临时目录
factory.setSizeThreshold(1024*1024*10);
ServletFileUpload upload = new ServletFileUpload(factory);
//最大上传限制
upload.setSizeMax(1024*1024*200);
//设置监听器监听上传进度
upload.setProgressListener(p);
List<FileItem> items = null;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
e.printStackTrace();
this.errorAndStorp(response, "alert('FileUploadExeception happened')", p,key);
}
for(Iterator<FileItem> it = items.iterator();it.hasNext();){
FileItem item = it.next();
if(item.isFormField()){
//处理表单域
}
else{
try {
FileOutputStream fos = new FileOutputStream(path+URLEncoder.encode(item.getName(),"utf-8"));
if(item.isInMemory()){//文件全在内存中
fos.write(item.get());
p.setComplete(true);
}
else{
InputStream is = item.getInputStream();
byte[] buffer = new byte[1024];
int len;
while((len = is.read(buffer)) > 0){
fos.write(buffer, 0, len);
}
p.setComplete(true);
is.close();
fos.close();
}
} catch (Exception e) {
e.printStackTrace();
this.errorAndStorp(response, "alert('Exception happened')", p,key);}
}
}
}
//上传线程一旦出现意外,就让progress出于完成状态以终止向客户端发送信息的线程
private void errorAndStorp(HttpServletResponse response,String script,
Progress p,String key)
throws IOException{
p.setComplete(true);
chp.remove(key);
this.sendMsg(response, script);
}
//向客户端发送数据
private void sendMsg(HttpServletResponse response,String script) throws IOException{
PrintWriter out = response.getWriter();
out.println("<script type='text/javascript'>" +script +"</script>");
//ie太拽了发送的字节少了它根本不掉你
out.println("---------------------------------------------------");
out.println("---------------------------------------------------");
out.println("---------------------------------------------------");
out.println("---------------------------------------------------");
out.flush();
}
//存放文件上传进度
private static class Progress implements ProgressListener{
private long length = 0;//文件总长度
private long currentLength = 0;//已上传的文件长度
private boolean isComplete = false;//上传是否完成
//实现监听器方法实时更新进度属性
public void update(long bytesRead, long contentLength, int items) {
currentLength = bytesRead;
}
public Progress(){}
public long getLength() {
return length;
}
public void setLength(int l){
this.length = l;
}
public long getCurrentLength() {
return currentLength;
}
public void setCurrentLenght(int cl){
this.currentLength = cl;
}
public boolean isComplete() {
return isComplete;
}
public void setComplete(boolean isComplete) {
this.isComplete = isComplete;
}
}
}
前台
<%@ page language="java" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>ajax显示上传文件进度</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<!--
<link rel="stylesheet" type="text/css" href="styles.css" mce_href="styles.css">
-->
<mce:style type="text/css"><!--
iframe{
border:0;
}
#p_out{
width:200px;
height:12px;
margin:10px 0 0 0;
padding:1px 1px 1px 1px;
font-size:10px;
border:solid #d4e4ff 1px;
}
#p_in{
width:0%;
height:100%;
background-color:#d4e4ff;
margin:0;
padding:0;
}
#dis{
margin:0;
padding:0;
text-align:center;
font-size:12px;
height:12px;
width:200px;
}
--></mce:style><mce:style type="text/css" mce_bogus="1"><!--
iframe{
border:0;
}
#p_out{
width:200px;
height:12px;
margin:10px 0 0 0;
padding:1px 1px 1px 1px;
font-size:10px;
border:solid #d4e4ff 1px;
}
#p_in{
width:0%;
height:100%;
background-color:#d4e4ff;
margin:0;
padding:0;
}
#dis{
margin:0;
padding:0;
text-align:center;
font-size:12px;
height:12px;
width:200px;
}
--></mce:style><style type="text/css" mce_bogus="1" mce_bogus="1"> iframe{
border:0;
}
#p_out{
width:200px;
height:12px;
margin:10px 0 0 0;
padding:1px 1px 1px 1px;
font-size:10px;
border:solid #d4e4ff 1px;
}
#p_in{
width:0%;
height:100%;
background-color:#d4e4ff;
margin:0;
padding:0;
}
#dis{
margin:0;
padding:0;
text-align:center;
font-size:12px;
height:12px;
width:200px;
}
</style>
</head>
<body>
<form id="uploadfile_form" name="uploadfile_form" enctype="multipart/form-data"
method="post" target="uploadfile_iframe">
<input type="file" name="file" />
<br><br>
<button onclick="progress()">提交</button>
<div id="p_out"><div id="p_in"></div></div>
<div id="dis"></div>
</form>
<iframe width="0px" height="0px" id="uploadfile_iframe" name="uploadfile_iframe" src="javascript:void(0)" ></iframe>
<iframe width="0px" height="0px" id="progress_iframe" name="progress_iframe" src="javascript:void(0)" ></iframe>
</body>
<script type="text/javascript">
function progress(){
document.getElementById('progress_iframe').src = 'myFileUpload';
document.getElementById('dis').innerHTML = '初始化数据...';
}
function uploadFile(k){
console.log("k="+k);
document.forms[0].action = 'myFileUpload?key='+k;
document.forms[0].submit();
}
function upload(len,total){
console.log("len="+len+"total="+total);
document.getElementById('p_in').style.width = (Math.round(len/total*100))+'%';
document.getElementById('dis').innerHTML = len+'/'+total+' Byte';
}
</script>
</html>
web.xml
<?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">
<display-name></display-name>
<servlet>
<servlet-name>myFileUpload</servlet-name>
<servlet-class>com.scott.uploadfile.UploadFile</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myFileUpload</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
导入commons-fileupload-1.3.1.jar,commons-io-2.2.jar
注:原文地址http://blog.youkuaiyun.com/tom_221x/article/details/3777064
本文介绍了一个使用多线程技术实现的文件上传进度显示的Java示例。通过自定义进度监听器,该示例能够实时更新客户端的文件上传进度,并在服务器端处理文件上传过程。
341

被折叠的 条评论
为什么被折叠?



