基於浏覽器的文件上傳,特別是對於通過<input type="file">標簽來實現上傳的情況, 存在著嚴重的性能問題,因為用戶提交了文件之後,在浏覽器把文件上傳到服務器的過程中,界面看上去似乎是靜止的,如果是小文件還好些,如果不幸需要上傳的是幾兆、幾十兆甚至上百兆的文件,我相信那是一種非常痛苦的體驗,我們中間的很多人應該都有過此種不堪的經歷。(一笑)
現在我就針對這個問題給出一個解決方案,我們將實現一個具有監控能力的WEB上傳的程序——它不僅把文件上傳到服務器,而且"實時地"監視文件上傳的實際過程。
解決方案的基本思路是這樣的:
在介紹源代碼之前,我們先來看看程序運行界面:
實現代碼想當然的有服務器端代碼和客戶端代碼(呵呵),我們先從服務器端開始。
使用FileUploadStatus這個類記錄文件上傳狀態,並將其作為服務器端與web客戶端之間通信的媒介,通過對這個類對象提供上傳狀態作為服務器回應發送給web客戶端, web客戶端使用JavaScript獲得文件上傳狀態。源代碼如下:
/** * 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。 * 如果需要轉載本例程,請您注明作者。 * * 作者: 劉作晨 * 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; //當前上傳文件號 private int currentUploadFileNum = 0; //成功讀取上傳文件數 private int successUploadFileCount = 0; //狀態 private String status = ""; //處理起始時間 private long processStartTime = 0l; //處理終止時間 private long processEndTime = 0l; //處理執行時間 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(); } }
使用Common-FileUpload 1.2版本(20070103)。此版本提供了能夠監視文件上傳情況的ProcessListener接口,使開發者通過FileUploadBase類對象的setProcessListener方法植入自己的Listener。 FileUploadListener類實現了ProcessListener,在整個文件上傳過程中,它對上傳進度進行監控,並且根據上傳 情況實時的更新上傳狀態Bean。源代碼如下:
/** * 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。 * 如果需要轉載本例程,請您注明作者。 * * 作者: 劉作晨 * 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; } /** * 更新狀態 */ public void update(long pBytesRead, long pContentLength, int pItems){ FileUploadStatus statusBean= BackGroundService.getStatusBean(request); statusBean.setUploadTotalSize(pContentLength); //讀取完成 if (pContentLength == -1) { statusBean.setStatus("完成對" + pItems +"個文件的讀取:讀取了 " + pBytesRead + " bytes."); statusBean.setReadTotalSize(pBytesRead); statusBean.setSuccessUploadFileCount(pItems); statusBean.setProcessEndTime(System.currentTimeMillis()); statusBean.setProcessRunningTime(statusBean.getProcessEndTime()); //讀取中 } else { statusBean.setStatus("當前正在處理第" + pItems +"個文件:已經讀取了 " + pBytesRead +
"/" + pContentLength+ " bytes."); statusBean.setReadTotalSize(pBytesRead); statusBean.setCurrentUploadFileNum(pItems); statusBean.setProcessRunningTime(System.currentTimeMillis()); } BackGroundService.saveStatusBean(request,statusBean); } }
當前1/2頁 12下一頁閱讀全文