1. 引言
基于瀏覽器的文件上傳,特別是對(duì)于通過input type="file">標(biāo)簽來實(shí)現(xiàn)上傳的情況, 存在著嚴(yán)重的性能問題,因?yàn)橛脩籼峤涣宋募?,在瀏覽器把文件上傳到服務(wù)器的過程中,界面看上去似乎是靜止的,如果是小文件還好些,如果不幸需要上傳的是幾兆、幾十兆甚至上百兆的文件,我相信那是一種非常痛苦的體驗(yàn),我們中間的很多人應(yīng)該都有過此種不堪的經(jīng)歷。(一笑)
現(xiàn)在我就針對(duì)這個(gè)問題給出一個(gè)解決方案,我們將實(shí)現(xiàn)一個(gè)具有監(jiān)控能力的WEB上傳的程序——它不僅把文件上傳到服務(wù)器,而且"實(shí)時(shí)地"監(jiān)視文件上傳的實(shí)際過程。
解決方案的基本思路是這樣的:
- 在Form提交上傳文件同時(shí),使用AJAX周期性地從Servlet輪詢上傳狀態(tài)信息
- 然后,根據(jù)此信息更新進(jìn)度條和相關(guān)文字,及時(shí)反映文件傳輸狀態(tài)
- 如果用戶取消上傳操作,則進(jìn)行相應(yīng)的現(xiàn)場清理工作:刪除已經(jīng)上傳的文件,在Form提交頁面中顯示相關(guān)信息
- 如果上傳完畢,顯示已經(jīng)上傳的文件內(nèi)容(或鏈接)
在介紹源代碼之前,我們先來看看程序運(yùn)行界面:
2. 實(shí)現(xiàn)代碼
實(shí)現(xiàn)代碼想當(dāng)然的有服務(wù)器端代碼和客戶端代碼(呵呵),我們先從服務(wù)器端開始。
2.1. 服務(wù)器端代碼
2.1.1. 文件上傳狀態(tài)類(FileUploadStatus)
使用FileUploadStatus這個(gè)類記錄文件上傳狀態(tài),并將其作為服務(wù)器端與web客戶端之間通信的媒介,通過對(duì)這個(gè)類對(duì)象提供上傳狀態(tài)作為服務(wù)器回應(yīng)發(fā)送給web客戶端, web客戶端使用JavaScript獲得文件上傳狀態(tài)。源代碼如下:
/** * 本例程演示了通過Web上傳文件過程中的進(jìn)度顯示。您可以對(duì)本例程進(jìn)行任何修改和使用。 * 如果需要轉(zhuǎn)載本例程,請(qǐng)您注明作者。 * * 作者: 劉作晨 * EMail:liuzuochen@gmail.com */ package liuzuochen.sample.upload; import java.util.*; public class FileUploadStatus { //上傳用戶地址 private String uploadAddr; //上傳總量 private long uploadTotalSize = 0; //讀取上傳總量 private long readTotalSize = 0; //當(dāng)前上傳文件號(hào) private int currentUploadFileNum = 0; //成功讀取上傳文件數(shù) private int successUploadFileCount = 0; //狀態(tài) private String status = ""; //處理起始時(shí)間 private long processStartTime = 0l; //處理終止時(shí)間 private long processEndTime = 0l; //處理執(zhí)行時(shí)間 private long processRunningTime = 0l; //上傳文件URL列表 private List uploadFileUrlList = new ArrayList(); //取消上傳 private boolean cancel = false; //上傳base目錄 private String baseDir = ""; public FileUploadStatus() { } public String getBaseDir() { return baseDir; } public void setBaseDir(String baseDir) { this.baseDir = baseDir; } public boolean getCancel() { return cancel; } public void setCancel(boolean cancel) { this.cancel = cancel; } public List getUploadFileUrlList() { return uploadFileUrlList; } public void setUploadFileUrlList(List uploadFileUrlList) { this.uploadFileUrlList = uploadFileUrlList; } public long getProcessRunningTime() { return processRunningTime; } public void setProcessRunningTime(long processRunningTime) { this.processRunningTime = processRunningTime; } public long getProcessEndTime() { return processEndTime; } public void setProcessEndTime(long processEndTime) { this.processEndTime = processEndTime; } 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 int getSuccessUploadFileCount() { return successUploadFileCount; } public void setSuccessUploadFileCount(int successUploadFileCount) { this.successUploadFileCount = successUploadFileCount; } public int getCurrentUploadFileNum() { return currentUploadFileNum; } public void setCurrentUploadFileNum(int currentUploadFileNum) { this.currentUploadFileNum = currentUploadFileNum; } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public long getUploadTotalSize() { return uploadTotalSize; } public String getUploadAddr() { return uploadAddr; } public void setUploadTotalSize(long uploadTotalSize) { this.uploadTotalSize = uploadTotalSize; } public void setUploadAddr(String uploadAddr) { this.uploadAddr = uploadAddr; } public String toJSon() { StringBuffer strJSon = new StringBuffer(); strJSon.append("{UploadTotalSize:").append(getUploadTotalSize()).append( ",") .append("ReadTotalSize:").append(getReadTotalSize()).append(",") .append("CurrentUploadFileNum:").append(getCurrentUploadFileNum()). append(",") .append("SuccessUploadFileCount:").append( getSuccessUploadFileCount()).append(",") .append("Status:'").append(getStatus()).append("',") .append("ProcessStartTime:").append(getProcessStartTime()). append(",") .append("ProcessEndTime:").append(getProcessEndTime()).append( ",") .append("ProcessRunningTime:").append(getProcessRunningTime()). append(",") .append("Cancel:").append(getCancel()).append("}"); return strJSon.toString(); } }
2.1.2. 文件上傳狀態(tài)偵聽類(FileUploadListener)
使用Common-FileUpload 1.2版本(20070103)。此版本提供了能夠監(jiān)視文件上傳情況的ProcessListener接口,使開發(fā)者通過FileUploadBase類對(duì)象的setProcessListener方法植入自己的Listener。 FileUploadListener類實(shí)現(xiàn)了ProcessListener,在整個(gè)文件上傳過程中,它對(duì)上傳進(jìn)度進(jìn)行監(jiān)控,并且根據(jù)上傳 情況實(shí)時(shí)的更新上傳狀態(tài)Bean。源代碼如下:
/** * 本例程演示了通過Web上傳文件過程中的進(jìn)度顯示。您可以對(duì)本例程進(jìn)行任何修改和使用。 * 如果需要轉(zhuǎn)載本例程,請(qǐng)您注明作者。 * * 作者: 劉作晨 * EMail:liuzuochen@gmail.com */ package liuzuochen.sample.upload; import org.apache.commons.fileupload.ProgressListener; import javax.servlet.http.HttpServletRequest; public class FileUploadListener implements ProgressListener{ private HttpServletRequest request=null; public FileUploadListener(HttpServletRequest request){ this.request=request; } /** * 更新狀態(tài) */ public void update(long pBytesRead, long pContentLength, int pItems){ FileUploadStatus statusBean= BackGroundService.getStatusBean(request); statusBean.setUploadTotalSize(pContentLength); //讀取完成 if (pContentLength == -1) { statusBean.setStatus("完成對(duì)" + pItems +"個(gè)文件的讀取:讀取了 " + pBytesRead + " bytes."); statusBean.setReadTotalSize(pBytesRead); statusBean.setSuccessUploadFileCount(pItems); statusBean.setProcessEndTime(System.currentTimeMillis()); statusBean.setProcessRunningTime(statusBean.getProcessEndTime()); //讀取中 } else { statusBean.setStatus("當(dāng)前正在處理第" + pItems +"個(gè)文件:已經(jīng)讀取了 " + pBytesRead +
"/" + pContentLength+ " bytes."); statusBean.setReadTotalSize(pBytesRead); statusBean.setCurrentUploadFileNum(pItems); statusBean.setProcessRunningTime(System.currentTimeMillis()); } BackGroundService.saveStatusBean(request,statusBean); } }
12下一頁閱讀全文您可能感興趣的文章:
- Jsp頁面實(shí)現(xiàn)文件上傳下載類代碼
- jsp中點(diǎn)擊圖片彈出文件上傳界面及預(yù)覽功能的實(shí)現(xiàn)
- jsp實(shí)現(xiàn)文件上傳下載的程序示例
- Jsp+Servlet實(shí)現(xiàn)文件上傳下載 文件上傳(一)
- jsp文件上傳與下載實(shí)例代碼
- jsp中點(diǎn)擊圖片彈出文件上傳界面及實(shí)現(xiàn)預(yù)覽實(shí)例詳解
- 利用jsp+Extjs實(shí)現(xiàn)動(dòng)態(tài)顯示文件上傳進(jìn)度
- jsp 文件上傳瀏覽,支持ie6,ie7,ie8
- servlet+JSP+mysql實(shí)現(xiàn)文件上傳的方法
- JSP實(shí)現(xiàn)文件上傳功能