带进度条的文件上传

最近在做一个文件上传的问题,其中遇到不少问题,Struts2实现了上传框架处理上传文件,使大伙方便安全地实现文件上传,但是许多功能的实现,只是用Struts2封装的上传框架是远远不够的,比如带进度条的文件上传,本人是找不到在运用struts的上传框架的基础上都不怎么实现,希望博友们能提供好的实现方法。于是我只能利用开源的commons-fileupload-XX.XX.jar实现所需功能。
但是其中出现了如下问题:如果在Struts2的Action里完成业务功能,拿到的文件上传请求已由Struts2的Action管理处理,你就会发现upload.parseRequest(request).getSize()拿到的大小为0。
于是我用Servlet来完成,希望文件请求直接交由Servlet来处理,一开始时Struts会出现找不到此Action的错误,原因是我在web.xml配置Struts2过滤路径的时候用<url-pattern>/*</url-pattern>,因此Servlet会交由Struts管理,并当成Action处理,结果就会报找不到Action的错误。
其中一种解决方法:对<url-pattern>进行重新定义,不再用/*,而是匹配到具体的应用。如用:/xx/*
(有关Tomcat中Filter的<url-pattern>匹配规则,请查看上一篇博文: http://blog.sina.com.cn/s/blog_7d0b04e70101mclr.html

另外一种解决方法:重新定义Struts的Filter
package com.struts.core.filter;
import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter;

public class PBLStrutsPrepareAndExecuteFilter extends
		StrutsPrepareAndExecuteFilter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
	        String requestURI = ((HttpServletRequest) request).getRequestURI();
	        /*过滤指定URI,使其Servlet不进入Sturts中*/
	        if(requestURI != null && requestURI.contains("Servlet"))              
	        	chain.doFilter(request, response);        
	        else
	            super.doFilter(request, response, chain);        //交由Struts管理
	}

}

此外,后台服务器应当有一个进度管理器(FileUploadStatusManager)来管理文件上传进度状态(FileUploadStatus),再通过commons-fileupload-xx.xx.jar中提供文件上传时的监听器FileUploadListener),更新进度管理器(FilUploadStatusManger)中的文件上传进度状态(FileUploadStatus)。
当然啦,有的人会把上传进度状态存在session里面,进行会话,但是我个人觉得有点不妥!

先贴一下效果如何
1)
2)

下面是部份源码:

文件上传进度状态(FileUploadStatus.java)
package com.frozenwind.upload.util;


/**
 * 一个用户上传文件由一个FileUploadStatus管理
 * 其中通过上传用户地址uploadAddr标志该FileUploadStatus的唯一性
 * 每个FileUploadStatus由单例FileUploadStatusManager管理
 * @author Frozenwind
 *
 */
public class FileUploadStatus {
	public final  static String SUCCESS="success";
	public final static String FAIL="fail";
	public final static String CANCEL="cancel";
	public final static String UPLOADING="uploading";
	public final static String  ERROR="error";
	// 上传总量
	private long uploadTotalSize = 0;
	// 读取上传总量
	private long readTotalSize = 0;
	// 状态
	private String status = "";
	// 处理起始时间
	private long processStartTime = 0l;

	private String filename=null;


	public FileUploadStatus() {
		
	}



	public long getProcessStartTime() {
		return processStartTime;
	}

	public void setProcessStartTime(long processStartTime) {
		this.processStartTime = processStartTime;
	}

	public long getReadTotalSize() {
		return readTotalSize;
	}

	public void setReadTotalSize(long readTotalSize) {
		this.readTotalSize = readTotalSize;
	}


	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public long getUploadTotalSize() {
		return uploadTotalSize;
	}

	

	public void setUploadTotalSize(long uploadTotalSize) {
		this.uploadTotalSize = uploadTotalSize;
	}

	


	public String toJSon() {
		StringBuffer strJson=new StringBuffer();
		strJson.append("{");
		strJson.append("\"uploadTotalSize\":"+uploadTotalSize/1024);
		strJson.append(",\"readTotalSize\":"+readTotalSize/1024);
		strJson.append(",\"status\":\""+status+"\"");
		strJson.append(",\"processStartTime\":"+ processStartTime);
		strJson.append(",\"filename\":\""+filename+"\"");
		strJson.append("}");
		return strJson.toString();
	}


	public String getFilename() {
		return filename;
	}


	public void setFilename(String filename) {
		this.filename = filename;
	}
}

进度管理器(FilUploadStatusManger.java)

package com.frozenwind.upload.util;

import java.util.HashMap;
import java.util.Map;

/**
 * FileUploadStatus的Bean管理器,用单例模式
 * @author Frozenwind
 *
 */
public class FileUploadStatusManager {
	private static FileUploadStatusManager fileUploadStatusManager = new FileUploadStatusManager();
	private  Map<String, FileUploadStatus> beans = new HashMap<String, FileUploadStatus>();

	private FileUploadStatusManager() {
	}

	public static synchronized FileUploadStatusManager getInstance() {
		return fileUploadStatusManager;
	}

	/**
	 * 创建FileUploadStatus类对象
	 * 
	 * @param uploadAddr通过request
	 *                .getRomotAddr获取
	 * @return
	 */
	public synchronized  FileUploadStatus createFileUploadStatus(String uploadAddr) {
		System.out.println("creat:"+uploadAddr+"("+beans.size()+")");
		FileUploadStatus fus = new FileUploadStatus();
		fus.setProcessStartTime(System.currentTimeMillis());
		beans.put(uploadAddr, fus);
		return fus;

	}

	/**
	 * 取得相应FileUploadStatus类对象
	 * 
	 * @param uploadAddr通过request
	 *                .getRomotAddr获取
	 * @return
	 */
	public synchronized  FileUploadStatus getUploadStatus(String uploadAddr) {
		System.out.println("get:"+uploadAddr+"("+beans.size()+")");
		return beans.get(uploadAddr);
	}

	/**
	 * 删除FileUploadStatus类对象
	 * 
	 * @param uploadAddr通过request
	 *                .getRomotAddr获取
	 */
	public synchronized  void removeFileUploadStatus(String uploadAddr) {
		beans.remove(uploadAddr);
	}

	/**
	 * 更新FileUploadStatus类对象
	 * 
	 * @param uploadAddr通过request
	 *                .getRomotAddr获取
	 * @param fileUploadStatus
	 */
	public synchronized  void setFileUploadStatus(String uploadAddr,
			FileUploadStatus fileUploadStatus) {
		System.out.println("set:"+uploadAddr+"("+beans.size()+")");
		beans.put(uploadAddr, fileUploadStatus);
	}
}

文件上传监听器(FileUploadListener.java)
package com.frozenwind.upload.util;

import org.apache.commons.fileupload.ProgressListener;

public class FileUploadListener implements ProgressListener{
	private static FileUploadStatusManager fileUploadStatusManager=FileUploadStatusManager.getInstance();
	private String  remoteAddr=null;
	public FileUploadListener(String remoteAddr){
		this.remoteAddr=remoteAddr;
	
	}

	/**
	 * 更新状态
	 */
	public void update(long pBytesRead, long pContentLength, int pItems){
		FileUploadStatus statusBean=fileUploadStatusManager .getUploadStatus(remoteAddr);
		 statusBean.setUploadTotalSize(pContentLength);
		 statusBean.setReadTotalSize(pBytesRead);
		 if(statusBean.getStatus()!=null&&statusBean.getStatus().equals(FileUploadStatus.CANCEL))
			 return;
				//读取完成
	    if (pContentLength == pBytesRead) {
	       statusBean.setStatus(FileUploadStatus.SUCCESS);

	    //读取中
	    } else if(pContentLength >pBytesRead){
	       statusBean.setStatus(FileUploadStatus.UPLOADING);
	    }
	    fileUploadStatusManager.setFileUploadStatus(remoteAddr, statusBean);
	}
}

页面代码:
<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>上传文件</title>
<script src="js/jquery-1.8.2.js"></script>
<script type="text/javascript" src="js/jquery.form.js"></script>

<style type="text/css">
#totalProgressBarBox {
	width: 200px;
	height: 5px;
	border: 1px inset;
	background: #eee;
	-webkit-border-radius: 4px;
	border-radius: 4px;
}

#totalProgressStatus {
	height: 5px;
	-webkit-border-radius: 4px;
	border-radius: 4px;
	background-color: #23C278;
}

</style>

<script>
	$(document).ready(function(e) {
		var refreshTiming = null; //刷新柄
		$("#uploadfileInput").change(
			function() {
				var options = {
					dataType : 'json',
					success : function(data) {
						if (data.status == null|| data.status == "") {
							alert("网络有问题,请检查你的网络再上传...");
						} else if (data.status == 'success') {
							console.info("上传成功...");
						} else if (data.satus == "error") {
							alert("服务器出现异常!");
						}

					}
				};
				$("#fileUploadForm").ajaxSubmit(options);   //源于juery.form
				startProgress();//上传文件处理
			});


			//上传处理
			function startProgress() {
				$("#progressBar").show("fast");
				$("#fileName").html($("#uploadfileInput").val());
				$("#progressStatusText").html('0%');
				//定时刷新
				refreshTiming = setInterval(refreshUploadStatus,
						100);
				return true;
			};

			//刷新上传状态
			function refreshUploadStatus() {
				$.get("UploadFileServlet",
					{
						"op" : "refresh"
					},
					function(uploadInfo) {
						console.info(uploadInfo.status);
						if (uploadInfo.status == null
								|| uploadInfo.status == "error") {
							alert("服务器出现在异常!");
						} else {
							var progressPercent = Math.ceil((uploadInfo.readTotalSize)/ uploadInfo.uploadTotalSize* 100);
							$("#progressStatusText").html(progressPercent+ '%');
							$("#totalProgressStatus").css("width",progressPercent+ '%');
							if (uploadInfo.status == null|| uploadInfo.status == ""|| uploadInfo.status == "success") {
								clearInterval(refreshTiming);
								refreshTiming = null;
								//请求更新数据库,并隐藏进度条,显示上传文见
								/* $.get("StudentSharedFile_updateDB",
									uploadInfo,
								 	function() {
									$("#uploading").hide("slow");
									window.location.reload();
								}); */
							}
	
						}
	
					}, 'json');

			}
		});
</script>
</head>
<body>
	<div id="wrapper">
		<div >
			<form id="fileUploadForm" action="UploadFileServlet?op=upload"
				method="post" enctype="multipart/form-data">
				<input type="file" id="uploadfileInput" value=""
					name="uploadfileInput">
			</form>
		</div>
		<div id="progressBar" style="display: none;" >
			<div id="theMeter" style="color: #333; font-size: 12px;">
				<div id="fileName">准备上传...</div>
				<div id="totalProgressBarBox" style="display: inline-block">
					<div id="totalProgressStatus" style="width: 0%;"></div>
				</div>
				<span id="progressStatusText">0%</span>
			</div>
		</div>
	</div>
</body>
</html>

Servlet业务逻辑处理:
package com.frozenwind.upload.servlet;

import java.io.File;
import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

import com.frozenwind.upload.util.FileUploadListener;
import com.frozenwind.upload.util.FileUploadStatus;
import com.frozenwind.upload.util.FileUploadStatusManager;



/**
 * Servlet implementation class UploadFileServlet
 */

@WebServlet("/UploadFileServlet")
public class UploadFileServlet extends HttpServlet {
	//private BaseDao baseDao = null;
/*@Override
	public void init() throws ServletException {
		ServletContext servletContext = this.getServletContext();
		WebApplicationContext ctx = WebApplicationContextUtils
				.getWebApplicationContext(servletContext);
		baseDao = (BaseDao) ctx.getBean("baseDao");

		super.init();
	}*/

	private static FileUploadStatusManager fileUploadStatusManger = FileUploadStatusManager
			.getInstance();
	private static final long serialVersionUID = 1L;
	private static String tempFilePath = "/upload/temp"; // 设置临时文件存储位置
	private static long fileSizeMax = 1024000000; // 设置单个文件的最大上传值
	private static long sizeMax = 1024000000; // 设置整个request的最大值
	private static String uploadPath = "/upload";
	private HttpServletRequest request = null;
	private HttpServletResponse response = null;
	private String encode="utf-8";
	String remoteAddr = null;

	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException,
			IOException {
		this.doPost(request, response);
	}

	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException,
			IOException {
		this.remoteAddr = request.getRemoteAddr();
		this.request = request;
		this.response = response;
		String op = request.getParameter("op");
		if (op == null & op.equals("")) {
			return;
		}
		if (op.equals("upload")) {
			this.processFileUpload();
		} else if (op.equals("refresh")) {
			this.responseStatusQuery();
		} else if (op.equals("cancel")) {
			this.processCancelFileUpload();
		} else
			System.out.println("No Action");
	}

	/**
	 * 上传文件处理
	 * 
	 * @return
	 * @throws IOException
	 */
	public String processFileUpload() {

		// 是否文件上传
		boolean isMultipart = ServletFileUpload
				.isMultipartContent(request);

		if (!isMultipart) {
			return null;
		}
		DiskFileItemFactory factory = new DiskFileItemFactory();
		// 设置内存缓冲区,超过后写入临时文件
		factory.setSizeThreshold(4960); // 40KB
		// factory.setSizeThreshold(10240000);
		// 设置临时文件存储位置
		File tempfile = new File(getServletContext().getRealPath(
				tempFilePath));
		if (!tempfile.isDirectory())
			tempfile.mkdir();
		factory.setRepository(tempfile);
		ServletFileUpload upload = new ServletFileUpload(factory);
		// 设置单个文件的最大上传值
		upload.setFileSizeMax(fileSizeMax);
		// 设置整个request的最大值
		upload.setSizeMax(sizeMax);
		upload.setProgressListener(new FileUploadListener(remoteAddr));
		// 保存初始化后的FileUploadStatus Bean
		// TODO 有待完善
		FileUploadStatus statusBean = fileUploadStatusManger
				.createFileUploadStatus(remoteAddr);
		try {
			List items = upload.parseRequest(request);
			// 获得返回url
			for (int i = 0; i < items.size(); i++) {
				FileItem item = (FileItem) items.get(i);
				if (item.isFormField()) {// 如果不是文件上传框,而是普通表单
					// TODO 一般参数处理
				} else if (item.getName().length() > 0) { // 处理文件上传
					String fileName = takeOutFileName(item
							.getName());
					File uploadedFile = new File(
							getServletContext()
									.getRealPath(uploadPath)
									+ File.separator
									+ fileName);

					FileUploadStatus satusBean = fileUploadStatusManger
							.getUploadStatus(remoteAddr);
					satusBean.setFilename(fileName);
					fileUploadStatusManger
							.setFileUploadStatus(
									remoteAddr,
									satusBean);
					item.write(uploadedFile);
					// 更新上传文件列表
				}
			}
		} catch (Exception e) {
			try {
				deleteUploadedFile();
				response.getWriter().print(
						"{\"status\":\"error\"}");
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			// uploadExceptionHandle("保存上传文件时发生错误:" +
			// e.getMessage());
			e.printStackTrace();
		}
		try {
			response.getWriter().print("{\"status\":\"success\"}");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return null;

	}

	/**
	 * 回应上传状态查询
	 * 
	 * @return
	 */
	public String responseStatusQuery() {
		response.setContentType("text/xml");
		response.setHeader("Cache-Control", "no-cache");
		response.setCharacterEncoding(encode);
		FileUploadStatus satusBean = fileUploadStatusManger
				.getUploadStatus(remoteAddr);
		if (satusBean == null)
			return null;
		try {
			//响应客户端
			response.getWriter().write(satusBean.toJSon());
			if (satusBean.getStatus().equals(
					FileUploadStatus.SUCCESS)) {
				fileUploadStatusManger.removeFileUploadStatus(remoteAddr);
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}
	void updateIntoDB(){
		
	}

	/**
	 * 处理取消文件上传
	 * 
	 * @return
	 */
	@Deprecated
	public String processCancelFileUpload() {

		FileUploadStatus satusBean = fileUploadStatusManger
				.getUploadStatus(request.getRemoteAddr());
		satusBean.setStatus(FileUploadStatus.CANCEL);
		fileUploadStatusManger.getUploadStatus(request.getRemoteAddr());
		try {
			response.getWriter().write(satusBean.toJSon());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	private void deleteUploadedFile() {
		FileUploadStatus satusBean = fileUploadStatusManger
				.getUploadStatus(remoteAddr);
		String fileName = satusBean.getFilename();
		if (fileName != null) {
			File uploadedFile = new File(getServletContext()
					.getRealPath(uploadPath)
					+ File.separator
					+ satusBean.getFilename());
			uploadedFile.delete();
		}
		fileUploadStatusManger.removeFileUploadStatus(remoteAddr);
	}

	/**
	 * 从文件路径中取出文件名
	 */
	private String takeOutFileName(String filePath) {
		int pos = filePath.lastIndexOf(File.separator);
		if (pos > 0) {
			return filePath.substring(pos + 1);
		} else {
			return filePath;
		}
	}
	

}


完整上传文件项目请查看下载:  http://download.csdn.net/detail/brozenwind/5903663

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值