DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> AJAX入門 >> AJAX詳解 >> AJAX實現基於WEB的文件上傳的進度控制
AJAX實現基於WEB的文件上傳的進度控制
編輯:AJAX詳解     

1. 引言 
2. 實現代碼 
2.1. 服務器端代碼 
2.1.1. 文件上傳狀態類(FileUploadStatus) 
2.1.2. 文件上傳狀態偵聽類(FileUploadListener) 
2.1.3. 後台服務類(BackGroundService) 
2.1.4. 文件上傳狀態控制類(BeanControler) 
2.2. 客戶端代碼 
2.2.1. AJaxWrapper.JS 
2.2.2. fileUpload.Html 
2.2.3. result.JSP 
2.2.4. fileUpload.CSS 
2.3. 配置文件 
3. 結語 
 1. 引言
返回
   基於浏覽器的文件上傳,特別是對於通過<input type="file">標簽來實現上傳的情況,
存在著嚴重的性能問題,因為用戶提交了文件之後,在浏覽器把文件上傳到服務器的過程中,界面看上去
似乎是靜止的,如果是小文件還好些,如果不幸需要上傳的是幾兆、幾十兆甚至上百兆的文件,我相信那是
一種非常痛苦的體驗,我們中間的很多人應該都有過此種不堪的經歷。(一笑)
  現在我就針對這個問題給出一個解決方案,我們將實現一個具有監控能力的WEB上傳的程序——它不僅
把文件上傳到服務器,而且"實時地"監視文件上傳的實際過程。
解決方案的基本思路是這樣的:


  在Form提交上傳文件同時,使用AJax周期性地從Servlet輪詢上傳狀態信息 
  然後,根據此信息更新進度條和相關文字,及時反映文件傳輸狀態 
  如果用戶取消上傳操作,則進行相應的現場清理工作:刪除已經上傳的文件,在Form提交頁面中顯示相關信息 
  如果上傳完畢,顯示已經上傳的文件內容(或鏈接) 
在介紹源代碼之前,我們先來看看程序運行界面:


 2. 實現代碼

返回

   實現代碼想當然的有服務器端代碼和客戶端代碼(呵呵),我們先從服務器端開始。

 2.1. 服務器端代碼

  2.1.1. 文件上傳狀態類(FileUploadStatus)

返回

   使用FileUploadStatus這個類記錄文件上傳狀態,並將其作為服務器端與web客戶端之間通信的媒介,通過對這個類對象提供上傳狀態作為服務器回應發送給web客戶端,web客戶端使用JavaScript獲得文件上傳狀態。源代碼如下:

        /**
* 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。
*
* 如需要轉載,請注明作者。
*
* 作者: 劉作晨
*
*/
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();

}
}

  2.1.2. 文件上傳狀態偵聽類(FileUploadListener)

返回

   使用Common-FileUpload 1.2版本(20070103)。此版本提供了能夠監視文件上傳情況的 ProcessListener接口,
使開發者通過FileUploaDBase類對象的setProcessListener方法植入自己的Listener。
FileUploadListener類實現了ProcessListener,在整個文件上傳過程中,它對上傳進度進行監控,
並且根據上傳 情況實時的更新上傳狀態Bean。源代碼如下:

 /**
* 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。
*
* 如需要轉載,請注明作者。
*
* 作者: 劉作晨
*
*/
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);
}
}

  2.1.3. 後台服務類(BackGroundService)

返回

   BackGroundService這個Servlet類負責接收Form Post數據、回應狀態輪詢請求、處理取消文件上傳的請求。
盡管可以把這些功能相互分離開來,但為了簡單明了,還是將它們放到Servlet中,只是由不同的方法進行分割。
源代碼如下:

  
/**
* 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。
*
* 如需要轉載,請注明作者。
*
* 作者: 劉作晨
*
*/
package liuzuochen.sample.upload;

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


import Javax.servlet.ServletException;
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.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.*;


public class BackGroundService extends javax.servlet.http.HttpServlet implementsJavax.servlet.Servlet {

public static final String UPLOAD_DIR = "/upload";
public static final String DEFAULT_UPLOAD_FAILURE_URL = "./result.JSP";

public BackGroundService() {
super();
}


protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,IOException {
doPost(request, response);
}
/**
* 從文件路徑中取出文件名
*/
private String takeOutFileName(String filePath) {
int pos = filePath.lastIndexOf(File.separator);
if (pos > 0) {
return filePath.substring(pos + 1);
} else {
return filePath;
}
}

/**
* 從request中取出FileUploadStatus Bean
*/
public static FileUploadStatus getStatusBean(
HttpServletRequest request) {
BeanControler beanCtrl = BeanControler.getInstance();
return beanCtrl.getUploadStatus(request.getRemoteAddr());
}
/**
* 把FileUploadStatus Bean保存到類控制器BeanControler
*/
public static void saveStatusBean(HttpServletRequest request,FileUploadStatus statusBean) {
statusBean.setUploadAddr(request.getRemoteAddr());
BeanControler beanCtrl = BeanControler.getInstance();
beanCtrl.setUploadStatus(statusBean);
}

/**
* 刪除已經上傳的文件
*/
private void deleteUploadedFile(HttpServletRequest request) {
FileUploadStatus satusBean = getStatusBean(request);
for (int i = 0; i < satusBean.getUploadFileUrlList().size(); i++) {
File uploadedFile = new File(request.getRealPath(UPLOAD_DIR) + File.separator + satusBean.getUploadFileUrlList(). get(i));
uploadedFile.delete();
}
satusBean.getUploadFileUrlList().clear();
satusBean.setStatus("刪除已上傳的文件");
saveStatusBean(request, satusBean);
}

/**
* 上傳過程中出錯處理
*/
private void uploadExceptionHandle(HttpServletRequest request,String errMsg) throws ServletException, IOException {
//首先刪除已經上傳的文件
deleteUploadedFile(request);
FileUploadStatus satusBean = getStatusBean(request);
satusBean.setStatus(errMsg);
saveStatusBean(request, satusBean);
}

/**
* 初始化文件上傳狀態Bean
*/
private FileUploadStatus initStatusBean(HttpServletRequest
request) {
FileUploadStatus satusBean = new FileUploadStatus();
satusBean.setStatus("正在准備處理");
satusBean.setUploadTotalSize(request.getContentLength());
satusBean.setProcessStartTime(System.currentTimeMillis());
satusBean.setBaseDir(request.getContextPath() + UPLOAD_DIR);
return satusBean;
}

/**
* 處理文件上傳
*/
private void processFileUpload(HttpServletRequest request,

HttpServletResponse response) throwsServletException, IOException {
DiskFileItemFactory factory = new DiskFileItemFactory();
//設置內存緩沖區,超過後寫入臨時文件
factory.setSizeThreshold(10240000);
//設置臨時文件存儲位置
factory.setRepository(new File(request.getRealPath("/upload/temp")));
ServletFileUpload upload = new ServletFileUpload(factory);
//設置單個文件的最大上傳值
upload.setFileSizeMax(102400000);
//設置整個request的最大值
upload.setSizeMax(102400000);
upload.setProgressListener(new FileUploadListener(request));
//保存初始化後的FileUploadStatus Bean
saveStatusBean(request, initStatusBean(request));

String forwardURL = "";
try {
List items = upload.parseRequest(request);
//獲得返回url
for (int i = 0; i < items.size(); i++) {
FileItem item = (FileItem) items.get(i);
if (item.isFormFIEld()) {
forwardURL = item.getString();
break;
}
}
//處理文件上傳
for (int i = 0; i < items.size(); i++) {
FileItem item = (FileItem) items.get(i);

//取消上傳
if (getStatusBean(request).getCancel()) {
deleteUploadedFile(request);
break;
}
//保存文件
else if (!item.isFormFIEld() && item.getName().length() > 0) {
String fileName = takeOutFileName(item.getName());
File uploadedFile = new File(request.getRealPath(UPLOAD_DIR) +
File.separator + fileName);item.write(uploadedFile);//更新上傳文件列表FileUploadStatus
satusBean =getStatusBean(request);
satusBean.getUploadFileUrlList().add(fileName);
saveStatusBean(request, satusBean);
Thread.sleep(500);
}
}

} catch (FileUploadException e) {
uploadExceptionHandle(request, "上傳文件時發生錯誤:" + e.getMessage());
} catch (Exception e) {
uploadExceptionHandle(request, "保存上傳文件時發生錯誤:" + e.getMessage());
}
if (forwardURL.length() == 0) {
forwardURL = DEFAULT_UPLOAD_FAILURE_URL;
}
request.getRequestDispatcher(forwardURL).forward(request, response);
}

/**
* 回應上傳狀態查詢
*/
private void responseStatusQuery(HttpServletRequest request,

HttpServletResponse response) throwsIOException {
response.setContentType("text/XML");
response.setCharacterEncoding("UTF-8");
response.setHeader("Cache-Control", "no-cache");
FileUploadStatus satusBean = getStatusBean(request);
response.getWriter().write(satusBean.toJSon());
}

/**
* 處理取消文件上傳
*/
private void processCancelFileUpload(HttpServletRequest request,

HttpServletResponse response) throwsIOException {
FileUploadStatus satusBean = getStatusBean(request);
satusBean.setCancel(true);
saveStatusBean(request, satusBean);
responseStatusQuery(request, response);
}

protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException,IOException {
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
processFileUpload(request, response);
} else {
request.setCharacterEncoding("UTF-8");

if (request.getParameter("uploadStatus") != null) {
responseStatusQuery(request, response);
}
if (request.getParameter("cancelUpload") != null) {
processCancelFileUpload(request, response);
}

}
}
}

  2.1.4. 文件上傳狀態控制類(BeanControler)

返回

   這是一個單例類,它的功能是為客戶端保存文件上傳狀態,這裡我沒有使用Session來存儲 文件上傳狀態,
因為對於AJax這種異步調用,服務器會開啟不同的Session,所以無法通過Session保存文件上傳狀態。
我並不認為這種方法最好,如果有更好的方法,歡迎大家一起討論。 源代碼如下:


/**
* 本例程演示了通過Web上傳文件過程中的進度顯示。您可以對本例程進行任何修改和使用。
*
* 如需要轉載,請注明作者。
*
* 作者: 劉作晨
*
*/
package liuzuochen.sample.upload;

import Java.util.Vector;

public class BeanControler {
private static BeanControler beanControler = new BeanControler();
private Vector vector = new Vector();
private BeanControler() {
}

public static BeanControler getInstance() {
return beanControler;
}

/**
* 取得相應FileUploadStatus類對象的存儲位置
*/
private int indexOf(String strID) {
int nReturn = -1;
for (int i = 0; i < vector.size(); i++) {
FileUploadStatus status = (FileUploadStatus) vector.elementAt(i);
if (status.getUploadAddr().equals(strID)) {
nReturn = i;
break;
}
}
return nReturn;
}
/**
* 取得相應FileUploadStatus類對象
*/
public FileUploadStatus getUploadStatus(String strID) {
return (FileUploadStatus) vector.elementAt(indexOf(strID));
}
/**
* 存儲FileUploadStatus類對象
*/
public void setUploadStatus(FileUploadStatus status) {
int nIndex = indexOf(status.getUploadAddr());
if ( -1 == nIndex) {
vector.add(status);
} else {
vector.insertElementAt(status, nIndex);
vector.removeElementAt(nIndex + 1);
}
}
/**
* 刪除FileUploadStatus類對象
*/
public void removeUploadStatus(String strID){
int nIndex = indexOf(strID);
if(-1!=nIndex)
vector.removeElementAt(nIndex);
}
}

 2.2. 客戶端代碼

   客戶端我們采用Prototype框架。

  2.2.1. AJaxWrapper.JS

返回

   AJaxWrapper.JS對Prototype進行了封裝。 源代碼如下:


//類工具
var ClassUtils=Class.create();
ClassUtils.prototype={
_ClassUtilsName:'ClassUtils',
initialize:function(){
},
/**
* 給類的每個方法注冊一個對類對象的自我引用
* @param reference 對類對象的引用
*/
registerFuncSelfLink:function(reference){
for (var n in reference) {
var item = reference[n];
if (item instanceof Function)
item.$ = reference;
}
}
}
//AJax操作封裝類:
//由於調用AJaxRequest類進行XMLHTTPRequest操作時,this引用(指向當前的對象)會出現了call stack問題,從而指向當前的對象。
//所以,對putRequest、callBackHandler、以及callback方法都要使用arguments.callee.$來獲得正確的類對象引用
var AJaxWrapper=Class.create();
AJaxWrapper.prototype={
debug_flag:false,
XML_source:'',
/**
* 初始化
* @param isDebug 是否顯示調試信息
*/
initialize:function(isDebug){
new ClassUtils().registerFuncSelfLink(this);
this.debug_flag=isDebug;

},
/**
* 以get的方式向server發送request
* @param url
* @param params
* @param callBackFunction 發送成功後回調的函數或者函數名
*/
putRequest:function(url,params,callBackFunction){
var funcHolder=arguments.callee.$;
var XMLHttp = new AJax.Request(url,
{
method: 'get',
parameters: params,
requestHeaders:['my-header-encoding','utf-8'],
onFailure: function(){
alert('對不起,網絡通訊失敗,請重新刷新!');
},
onSuccess: function(transport){
},
onComplete: function(transport){
funcHolder.callBackHandler.apply(funcHolder,[transport,callBackFunction]);
}
});
},
/**
* 以post的方式向server發送XML請求
* @param url
* @param postDataBody
* @param callBackFunction 發送成功後回調的函數或者函數名
*/
pushRequest:function(url,postDataBody,callBackFunction){
var funcHolder=arguments.callee.$;
var options={
method: 'post',
parameters:'',
requestHeaders:['my-header-encoding','utf-8'],
postBody: postDataBody,
onFailure: function(transport){
alert('對不起,網絡通訊失敗,請重新發送!');
},
onComplete: function(transport){
funcHolder.callBackHandler.apply(funcHolder,[transport,callBackFunction]);
}
};
var XMLHttp = new AJax.Request(url,options);
},
/**
* 遠程調用的回調處理
* @param transport XMLhttp的transport
* @param callBackFunction 回調時call的方法,可以是函數也可以是函數名
*/
callBackHandler:function(transport,callBackFunction){
var funcHolder=arguments.callee.$;
if(transport.status!=200){
alert("獲得回應失敗,請求狀態:"+transport.status);
}
else{
funcHolder.XML_source=transport.responseText;
if (funcHolder.debug_flag)
alert('call callback function');
if (typeof(callBackFunction)=='function'){
if (funcHolder.debug_flag){
alert('invoke callbackFunc');
}
callBackFunction(transport.responseText);
}
else{
if (funcHolder.debug_flag){
alert('evalFunc callbackFunc');
}
new execute().evalFunc(callBackFunction,transport.responseText);
}
if (funcHolder.debug_flag)
alert('end callback function');
}
},
//顯示XML信息
showXMLResponse:function(){
var funcHolder=arguments.callee.$;
alert(funcHolder.XML_source);
}
}

var XMLDomForAJax=Class.create();
XMLDomForAJax.prototype={
isDebug:false,
//dom節點類型常量
ELEMENT_NODE:1,
ATTRIBUTE_NODE:2,
TEXT_NODE:3,
CDATA_SECTION_NODE:4,
ENTITY_REFERENCE_NODE:5,
ENTITY_NODE:6,
PROCESSING_INSTRUCTION_NODE:7,
COMMENT_NODE:8,
DOCUMENT_NODE:9,
DOCUMENT_TYPE_NODE:10,
DOCUMENT_FRAGMENT_NODE:11,
NOTATION_NODE:12,

initialize:function(isDebug){
new ClassUtils().registerFuncSelfLink(this);
this.isDebug=isDebug;
},
/**
* 建立跨平台的dom解析器
* @param xml XML字符串
* @return dom解析器
*/
createDomParser:function(XML){
// code for IE
if (window.ActiveXObject){
var doc=new ActiveXObject("Microsoft.XMLDOM");
doc.async="false";
doc.loadXML(XML);
}
// code for Mozilla, Firefox, Opera, etc.
else{
var parser=new DOMParser();
var doc=parser.parseFromString(xml,"text/XML");
}
return doc;
},
/**
* 反向序列化XML到Javascript Bean
* @param xml XML字符串
* @return Javascript Bean
*/
deserializedBeanFromXML:function (XML){
var funcHolder=arguments.callee.$;
var doc=funcHolder.createDomParser(XML);
// documentElement總表示文檔的root
var objDomTree=doc.documentElement;
var obj=new Object();
for (var i=0; i0){
objFieldValue[objFIEldValue.length]=nodeText;
}
}
else{
objFIEldValue=new Array();
}
}
else if (node.getAttribute('type')=='long'
|| node.getAttribute('type')=='Java.lang.Long'
|| node.getAttribute('type')=='int'
|| node.getAttribute('type')=='Java.lang.Integer'){
objFIEldValue=parseInt(nodeText);
}
else if (node.getAttribute('type')=='double'
|| node.getAttribute('type')=='float'
|| node.getAttribute('type')=='Java.lang.Double'
|| node.getAttribute('type')=='Java.lang.Float'){

objFIEldValue=parseFloat(nodeText);
}
else if (node.getAttribute('type')=='Java.lang.String'){
objFIEldValue=nodeText;
}
else{
objFIEldValue=nodeText;
}
//賦值給對象
obj[node.getAttribute('name')]=objFIEldValue;
if (funcHolder.isDebug){
alert(eval('obj.'+node.getAttribute('name')));
}
}
else if (node.nodeType == funcHolder.TEXT_NODE){
if (funcHolder.isDebug){
//alert('TEXT_NODE');
}

}
else if (node.nodeType == funcHolder.CDATA_SECTION_NODE){
if (funcHolder.isDebug){
//alert('CDATA_SECTION_NODE');
}
}
}
return obj;
},
/**
* 獲得dom節點的text
*/
getNodeText:function (node) {
var funcHolder=arguments.callee.$;
// is this a text or CDATA node?
if (node.nodeType == funcHolder.TEXT_NODE || node.nodeType == funcHolder.CDATA_SECTION_NODE) {
return node.data;
}
var i;
var returnValue = [];
for (i = 0; i < node.childNodes.length; i++) {
//采用遞歸算法
returnValue.push(funcHolder.getNodeText(node.childNodes[i]));
}
return returnValue.join('');
}
}

//委托者類
var Dispatcher=Class.create();
Dispatcher.prototype={
name:'Dispatcher',
//對class中的每個function都賦值一個值為this的$屬性
initialize:function(){
new ClassUtils().registerFuncSelfLink(this);
},
/**
* 委托調用
* @param caller 調用者,func的擁有者
* @param func 如果是function對象,則使用Dispatcher對象自己的name作為參數;否則直接調用func
*/
dispatch:function(caller,func){
if (func instanceof Function){
var funcArguments=new Array();
funcArguments[0]=arguments.callee.$.name;
func.apply(caller,funcArguments);
}
else{
eval(func);
}
}
}
//祈禱者類
var Invoker=Class.create();
Invoker.prototype={
name:'Invoker',
initialize:function(){
},
invoke:function(showMsg){
alert(showMsg+"——this.name="+this.name);
}
}

  2.2.2. fileUpload.Html

返回

   fileUpload.Html是文件上傳界面。 源代碼如下:


<Html>
<head>
<meta http-equiv="Content-Type" content="text/Html; charset=GBK">
<script type="text/Javascript" src="./Javascript/prototype.JS"></script>
<script type="text/Javascript" src="./Javascript/AJaxWrapper.JS"></script>
<link href="./css/fileUpload.css" type="text/CSS" rel="stylesheet"/>
<title>文件上傳</title>

</head>
<body>
<div id="controlPanel">
<div id="readme">測試說明:  最大上傳量:100M,單個文件最大長度:100M</div>
<div id="uploadFileUrl"></div>

<form id="fileUploadForm" name="fileUploadForm" action="./BackGroundService.action"
enctype="multipart/form-data" method="post">
<input type="file" name="file" id="file" size="40"/><br>
<input type="file" name="file" id="file" size="40"/><br>
<input type="file" name="file" id="file" size="40"/><br>
<input type="submit" name="uploadButton" id="uploadButton" value="開始上傳"/>
<input type="button" name="cancelUploadButton" id="cancelUploadButton" value="取消上傳"/><br>
</form>
<div id="progressBar">
<div id="theMeter">
<div id="progressBarText"></div>
<div id="totalProgressBarBox">
<div id="totalProgressBarBoxContent"></div>
</div>
</div>
<div id="progressStatusText"></div>
</div>

</div>



<script>
Element.hide('progressBar');
Event.observe('fileUploadForm','submit',startProgress,false);
Event.observe('cancelUploadButton','click',cancelProgress,false);

//刷新上傳狀態
function refreshUploadStatus(){
var ajaxW = new AJaxWrapper(false);
AJaxW.putRequest(
'./BackGroundService.action',
'uploadStatus=',
function(responseText){
eval("uploadInfo = " + responseText);
var progressPercent = Math.ceil(
(uploadInfo.ReadTotalSize) / uploadInfo.UploadTotalSize * 100);

$('progressBarText').innerHtml = ' 上傳處理進度: '+progressPercent+'% ['+(uploadInfo.ReadTotalSize)+'/'+uploadInfo.UploadTotalSize + ' bytes]'+
' 正在處理第'+uploadInfo.CurrentUploadFileNum+'個文件'+
' 耗時: '+(uploadInfo.ProcessRunningTime-uploadInfo.ProcessStartTime)+' ms';
$('progressStatusText').innerHtml=' 反饋狀態: '+uploadInfo.Status;
$('totalProgressBarBoxContent').style.width = parseInt(progressPercent * 3.5) + 'px';
}
);
}
//上傳處理
function startProgress(){
Element.show('progressBar');
$('progressBarText').innerHtml = ' 上傳處理進度: 0%';
$('progressStatusText').innerHtml=' 反饋狀態:';
$('uploadButton').disabled = true;
var periodicalExe=new PeriodicalExecuter(refreshUploadStatus,0.5);
return true;
}
//取消上傳處理
function cancelProgress(){
$('cancelUploadButton').disabled = true;
var ajaxW = new AJaxWrapper(false);
AJaxW.putRequest(
'./BackGroundService.action',
'cancelUpload=true',
//因為form的提交,這可能不會執行
function(responseText){
eval("uploadInfo = " + responseText);
$('progressStatusText').innerHtml=' 反饋狀態: '+uploadInfo.status;
if (msgInfo.cancel=='true'){
alert('刪除成功!');
window.location.reload();
};
}
);
}
</script>
</body>
</Html>

  2.2.3. result.JSP

返回

   result.JSP是文件上傳結果顯示界面。 源代碼如下:


<%@ page language="Java" contentType="text/Html; charset=GBK"pageEncoding="GBK"%>
<%@ page import="liuzuochen.sample.upload.*" %>
<Html>
<head>
<meta http-equiv="Content-Type" content="text/Html; charset=GBK">
<link href="./css/fileUpload.css" type="text/CSS" rel="stylesheet"/>
<title>文件上傳結果</title>
</head>
<body>
<div id="resultPanel">
<div><span>上傳文件列表:</span></div>
<%

FileUploadStatus fUploadStatus=BackGroundService.getStatusBean(request);

for(int i=0;i<fUploadStatus.getUploadFileUrlList().size();i++){
String fileName=(String)fUploadStatus.getUploadFileUrlList().get(i);
String url=fUploadStatus.getBaseDir()+"/"+fileName;
%>
<div><a href="<%=url%>"><%=fileName%></a></div>
<%
}
if (fUploadStatus.getStatus().indexOf("錯誤")>=0){
%>
<div id='errorArea'><span>錯誤信息:<%=fUploadStatus.getStatus() %></span></div>
<%
}
else if (fUploadStatus.getCancel()){
%>
<div id='normalMessageArea'><span>由於用戶取消上傳,所以已經上傳的文件均被刪除</span></div>
<%
}
BeanControler.getInstance().removeUploadStatus(request.getRemoteAddr());

%>
</div>
</body>
</Html>

  2.2.4. fileUpload.CSS

返回

   fileUpload.CSS是樣式文件。 源代碼如下:


body {
color:#000;
background-color:white;
font:15px Georgia, "Lucida Grande", Arial, sans-serif;
letter-spacing:0.01em;
margin:15px;
}
#controlPanel,#resultPanel{
width:700px;
margin:20px auto;
padding:25px;
border:3px solid gray;
-moz-border-radius:10px;
background:#f8f8f8;
}
#errorArea{
width:400px;
margin:20px auto;
padding:25px;
border:3px solid gray;
-moz-border-radius:10px;
background:red;
}
#normalMessageArea{
width:400px;
margin:20px auto;
padding:25px;
border:3px solid gray;
-moz-border-radius:10px;
background:yellow;
}
#progressBar { padding-top: 5px; }
#totalProgressBarBox {
width: 350px;
height: 20px;
border: 1px inset;
background: #eee;
}
#totalProgressBarBoxContent {
width: 0;
height: 20px;
border-right: 1px solid #444;
background: #9ACB34;
}

 2.3. 配置文件

返回

   把如下代碼加入web.XML中完成Servlet的配置。


<servlet>
<description>
</description>
<display-name>BackGroundService</display-name>
<servlet-name>BackGroundService</servlet-name>
<servlet-class>liuzuochen.sample.upload.BackGroundService</servlet-class>
</servlet>

<servlet-mapping>
<servlet-name>BackGroundService</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>

 3. 結語

返回

   整個程序到這裡就介紹完了,希望它多少能為您的工作或學習帶來點兒幫助。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved