1. 程式人生 > >servlet+jquery實現檔案上傳進度條

servlet+jquery實現檔案上傳進度條

      現在檔案的上傳,特別是大檔案上傳,都需要進度條,讓客戶知道上傳進度。

      本文簡單記錄下如何弄進度條,以及一些上傳資訊,比如檔案的大小,上傳速度,預計剩餘時間等一些相關資訊。程式碼是匆忙下簡單寫的,一些驗證沒做,或程式碼存在一些隱患,不嚴謹的地方。本文程式碼只供參考。

      進度條的樣式多種多樣,有些網站弄得非常絢爛漂亮。本文UI端不太懂,只會一些簡單的基本的css而已,所以進度條弄得不好看。本文側重的給讀者提供一個參考,一個實現思路而已。

     注:由於jquery版本用的是2.1.1,所以如果跑本例子原始碼,請用IE9以上或火狐、谷歌瀏覽器測試。

      


  接收檔案上傳的servlet

UploadFileServlet.java

package com.fei.servlet;

import java.io.IOException;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fei.util.FileUploadUtil;

public class UploadFileServlet extends HttpServlet {

	
	private static final long serialVersionUID = 1L;

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

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		try {
			long start = System.currentTimeMillis();
			System.out.println("開始上傳檔案........." );
			Map<String, String> params = FileUploadUtil.upload(request);
			System.out.println("檔案上傳完成........." );
			System.out.println("檔案上次用時:"+(System.currentTimeMillis()-start)+"毫秒");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

將上傳檔案進行下載到伺服器的處理

FileUploadUtil.java

package com.fei.util;

import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

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

public class FileUploadUtil {

	/**
	 * 檔案上傳儲存路徑
	 */
	private static final String SAVE_FILEPATH = "/fileupload/";
	/**
	 * 檔案上傳臨時儲存路徑
	 */
	private static final String SAVE_FILE_TMPPATH = "/fileupload/tmp/";
	/**
	 * 上傳檔案的最大值M
	 */
	private static final int MAX_FILE_SIZE = 100*1024*1024;
	/**
	 * 檔案資料在記憶體中超過多少M後,就寫入臨時檔案
	 */
	private static final int THRESHOLD_SIZE = 2*1024*1024;
	
	private static final String ENCODING = "UTF-8";
	
	/**
	 * 處理檔案上傳的表單
	 * 下載檔案,並返回檔名稱及普通表單域中其它屬性值
	 * 獲取檔名
	 */
	public static Map<String,String> upload(HttpServletRequest request)throws Exception{
		Map<String,String> params = new HashMap<String, String>();
		
		String savePath = request.getSession().getServletContext()
				.getRealPath(SAVE_FILEPATH)+ File.separator;
		String savePathTemp = request.getSession().getServletContext()
				.getRealPath(SAVE_FILE_TMPPATH)+ File.separator;
		
		File saveFileTempDir = new File(savePathTemp);
		
		DiskFileItemFactory factory = new DiskFileItemFactory();
		//當記憶體中檔案資料達到THRESHOLD_SIZE後,就寫入臨時檔案中,避免上傳大檔案時,消化太多記憶體
		factory.setSizeThreshold(THRESHOLD_SIZE);
		factory.setRepository(saveFileTempDir);
		
		ServletFileUpload upload = new ServletFileUpload(factory);
		upload.setHeaderEncoding(ENCODING);
		upload.setSizeMax(MAX_FILE_SIZE);
		
		FileUploadInfo fileUploadInfo = new FileUploadInfo();
		upload.setProgressListener(new FileUploadListener(fileUploadInfo));
		request.getSession().setAttribute("uploadInfo", fileUploadInfo);
		
		List items = upload.parseRequest(request);
		Iterator iter = items.iterator();
		int fileNum = 1;
		while(iter.hasNext()){
			FileItem item = (FileItem) iter.next();
			if (item.isFormField()) {//普通表單域
				params.put(item.getFieldName(), item.getString());
			} else {
				String fileName = item.getName().replace("/", "\\");
				int i = fileName.lastIndexOf("\\");
				fileName = fileName.substring(i+1);
				//避免重複
				fileName = System.currentTimeMillis() + fileName;
				
				File uploadedFile = new File(savePath + fileName);
				item.write(uploadedFile);
				
				params.put("fileName0"+fileNum, fileName);
				fileNum ++;

			}
		}
		
		
		return params;
	}
	
}

class FileUploadListener implements ProgressListener{

	FileUploadInfo fileUploadInfo = null;
	
	public FileUploadListener(FileUploadInfo fileUploadInfo) {
		this.fileUploadInfo = fileUploadInfo;
	}
	
	@Override
	public void update(long uploadSize, long totalSize, int itemNum) {
		this.fileUploadInfo.setTotalSize(totalSize);
		this.fileUploadInfo.setUploadSize(uploadSize);
		
	}
	
}
上傳檔案的一些資訊

FileUploadInfo.java

package com.fei.util;

public class FileUploadInfo {

	private final int K = 1024;
	
	private final int M = K * 1024;
	
	/**
	 * 總大小
	 */
	private long totalSize;
	/**
	 * 開始上傳時間
	 */
	private long startTime = System.currentTimeMillis();
	/**
	 * 已上傳多少
	 */
	private long uploadSize;
	
	/**
	 * 上傳速度(K/S)
	 */
	public double getUploadSpeed_K(){
		long currentTime = System.currentTimeMillis();
		long usedTime = currentTime - startTime;
		if(usedTime == 0.0){
			return 0.0;
		}
		return getUploadSize_K()/usedTime*1000d;
	}
	/**
	 * 獲取已上傳百分比
	 * @return
	 */
	public double getUploadPercent(){
		return (getUploadSize()*1.00/getTotalSize())*100d;
	}
	/**
	 * 剩餘時間(s)
	 * @return
	 */
	public double getRemainTime(){
		double speedKB = getUploadSpeed_K();
		if(speedKB<= 0.00){
			return -1d;
		}
		return (getTotalSize_K() - getUploadSize_K())/speedKB;
	}
	/**
	 * 已上傳時間
	 * @return
	 */
	public double getUseTime(){
		return (System.currentTimeMillis() - startTime)/1000d;
	}
	
	public long getTotalSize() {
		return totalSize;
	}
	
	public double getTotalSize_K(){
		return getTotalSize()*1.0/K;
	}
	
	public double getTotalSize_M(){
		return getTotalSize()*1.0/M;
	}
	
	public long getUploadSize() {
		return uploadSize;
	}
	
	public double getUploadSize_K(){
		return getUploadSize()/K;
	}
	
	public double getUploadSize_M(){
		return getUploadSize()/M;
	}
	
	public void setTotalSize(long totalSize) {
		this.totalSize = totalSize;
	}
	
	
	public void setUploadSize(long uploadSize) {
		this.uploadSize = uploadSize;
	}
	
	private String double2String(double d){
		return String.format("%.2f", d);
	}
	
	public String toString(){
		return  "{"+
				"'totalSize':'"+double2String(getTotalSize_M())+"M',"+
				"'uploadSize':'"+double2String(getUploadSize_M())+"M',"+
				"'uploadSpeed':'"+double2String(getUploadSpeed_K())+"KB/s',"+
				"'uploadPrecent':'"+double2String(getUploadPercent())+"',"+
				"'remainTime':'"+(getRemainTime()<0?"未知":double2String(getRemainTime()))+"s"+"',"+
				"'useTime':'"+double2String(getUseTime())+"s' "+
				"}";
	}
}

讀取檔案上傳進度的servlet

UploadFileProgressServlet.java

package com.fei.servlet;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.fei.util.FileUploadInfo;

public class UploadFileProgressServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String responseContent = "";
		
		Object obj = request.getSession().getAttribute("uploadInfo");
		if(obj == null){
			responseContent = "{'data':'NoData'}";
		}else{
			FileUploadInfo uploadInfo = (FileUploadInfo)obj;
			responseContent = uploadInfo.toString();
			if(uploadInfo.getUploadPercent()== 100.0){
				request.getSession().setAttribute("uploadInfo", null);
			}
		}
		System.out.println("檔案上次情況:"+responseContent);
		response.getWriter().print(responseContent);
	}
}

前臺頁面upload2.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="js/jquery-2.1.1.js" type="text/javascript"></script>

<script >
var falseNum = 0;
$(document).ready(function(){
	$('#subbut').bind('click',
			function(){
				$('#fForm').submit();
				var eventFun = function(){
		    		$.ajax({
	    				type: 'GET',
	    				url: '/uploadtest/UploadFileProgressServlet.do',
	    				data: {},
	    				dataType: 'text',
	    				success : function(resData){
					    	//如果10次都失敗,那就不要繼續訪問了
					    	if(falseNum > 10){
					    	  window.clearInterval(intId);
					    	  return;
					    	}
					    	var obj = eval("("+resData+")");
					    	if(obj.data == 'NoData'){
					    	   falseNum ++ ;
					    	   return;
					    	}
					    	$("#graphbox").css('display','block');
					    	$(".progressbar").css('width',obj.uploadPrecent+'%');
					    	$("#uploadPer").html(obj.uploadPrecent+'%');
					    	$("#progressInfo").html('總大小:'+obj.totalSize
					    			+',速度:'+obj.uploadSpeed
					    			+'%,剩餘時間:'+obj.remainTime+',已用時間:'+obj.useTime);
					    	if(obj.uploadPrecent == 100){
					    		window.clearInterval(intId);
					    		$("#progressInfo").html("上傳成功!");
					    	}	
	    		}});};
	    		var intId = window.setInterval(eventFun,500);
	});
});
</script>
<style>
#graphbox{
border:1px solid #e7e7e7;
padding:5px;
width:350px;
background-color:#f8f8f8;
margin:5px 0;
display:none;
}
.graph{
position:relative;
background-color:#F0EFEF;
border:1px solid #cccccc;
padding:2px;
font-size:10px;
font-weight:500;
}
.graph  .progressbar{
position:relative;
text-align:right;
color:#ffffff;
height:10px;
line-height:10px;
font-family:Arial;
display:block;
}
.graph .progressbar{background-color:#66CC33;}

</style>
</head>
<body>
		<form id='fForm' class="form-actions form-horizontal" action="/uploadtest/UploadFileServlet.do" 
		      encType="multipart/form-data" target="uploadf" method="post">
				 <div class="control-group">
					<label class="control-label">上傳檔案:</label>
					<div class="controls">
						<input type="file"  name="file" style="width:350px"></br>
						<input type="file"  name="file2" style="width:350px"></br>
						<button type="button" id="subbut" class="btn">上傳</button>	
					</div>
					<div id="graphbox">
						<div class="graph">
						<span class="progressbar" style="width:0%;"><span id="uploadPer"></span></span>
						</div>
					</div>
					<div id='progressInfo'>
					</div>
				</div>
		</form>
		<iframe name="uploadf" style="display:none"></iframe>
</body>
</html>

    將專案部署到tomcat(或其他web容器),訪問http://172.16.126.128:8080/uploadtest/upload2.html

效果:



 程式碼下載