Ajax技術——帶進度條的文件上傳

1.概述

      在實際的Web應該開發或網站開發過程當中,常常須要實現文件上傳的功能。在文件上傳過程當中,常常須要用戶進行長時間的等待,爲了讓用戶及時瞭解上傳進度,能夠在上傳文件的同時,顯示文件的上傳進度條。運行本實例,如圖1所示,訪問文件上傳頁面,單擊「瀏覽」按鈕選擇要上傳的文件,注意文件不能超過50MB,不然系統將給出錯誤提示。選擇完要上傳的文件後,單擊「提交」按鈕,將會上傳文件並顯示上傳進度。javascript

 

2.技術要點

     主要是應用開源的Common-FileUpload組件來實現分段文件上傳,從而實如今上傳過程當中,不斷獲取上傳進度。下面對Common-FileUpload組件進行詳細介紹。html

     Common-FileUpload組件時Apache組織下的jakarta-commons項目下的一個子項目,該組件能夠方便地將multipart/form-data類型請求中的各類表單域解析出來。該組件須要另外一個名爲Common-IO的組件的支持。這兩個組件包文件能夠到http://commons.apache.org網站上進行下載。java

(1)建立上傳對象apache

在應該Common-FileUpload組件實現文件上傳時,須要建立一個工廠對象,並根據該工廠對象建立一個新的文件上傳對象,具體代碼以下:服務器

DiskFileItemFactory factory = new DiskFileItemFactory();

ServletFileUpload upload = new ServletFileUpload(factory);

(2)解析上傳請求session

建立一個文件上傳對象後,就能夠應用該對象來解析上傳請求,獲取所有的表單項,能夠經過文件上傳對象的parseRequest()方法來實現。parseRequest()方法的語法結構以下:jsp

public List parseRequest(HttpServletRequest request) throws FileUploadException

(3)FileItem類函數

在Common-FileUpload組件中,不管是文件域仍是普通表單域,都當成FileItem對象來處理。若是該對象的isFormField()方法返回值爲true,則表示是一個普通表單域,不然爲一個文件域。在實現文件上傳時,能夠經過FileItem類的getName()方法得到上傳文件的文件名,經過getSize()方法得到上傳文件的大小。post

 

3.具體實現

(1)建立request.js文件,在該文件中編寫Ajax請求方法。網站

(2)新建文件上傳頁index.jsp,在該頁中添加用於得到上傳文件信息的表單以及表單元素,並添加用於顯示進度條的<div>標籤和顯示百分比的<span>標籤,關鍵代碼以下:

<form enctype="multipart/form-data" method="post" action="UpLoad?action=uploadFile">

     請選擇上傳的文件:<input name="file" type="file" size="34">

       注:文件大小請控制在50M之內。

     <div id="progressBar" class="prog_border" align="left">

            <img src="images/progressBar.gif" width="0" height="13" id="imgProgress"></div>

     <span id="progressPercent" style="width:40px;display:none">0%</span>

     <input name="Submit" type="button" value="提交" onClick="deal(this.form)">

         <input name="Reset" type="reset" class="btn_grey" value="重置"></td>

</form>

(3)新建上傳文件的Servlet實現類UpLpad。在該類中編寫實現文件上傳的方法uploadFile(),在該方法中經過Common-FileUpload組件實現分段上傳文件,並計算上傳百分比,實時保存到Session中,關鍵代碼以下:

public void uploadFile(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    response.setContentType("text/html;charset=GBK");
    request.setCharacterEncoding("GBK");
    HttpSession session=request.getSession();
    session.setAttribute("progressBar",0);                          //定義指定上傳進度的Session變量
    String error = "";
    int maxSize=50*1024*1024;                               //單個上傳文件大小的上限
    DiskFileItemFactory factory = new DiskFileItemFactory();     //建立工廠對象
    ServletFileUpload upload = new ServletFileUpload(factory);       //建立一個新的文件上傳對象
    try {
        List items = upload.parseRequest(request);                 // 解析上傳請求
        Iterator itr = items.iterator();                              // 枚舉方法
        while (itr.hasNext()) {
            FileItem item = (FileItem) itr.next();                  //獲取FileItem對象
            if (!item.isFormField()) {                                  // 判斷是否爲文件域
                if (item.getName() != null && !item.getName().equals("")) {//是否選擇了文件
                    long upFileSize=item.getSize();                //上傳文件的大小
                    String fileName=item.getName();            //獲取文件名
                    if(upFileSize>maxSize){
                        error="您上傳的文件太大,請選擇不超過50M的文件";
                        break;
                    }
                    // 此時文件暫存在服務器的內存中
                    File tempFile = new File(fileName);             //構造文件目錄臨時對象
                    String uploadPath = this.getServletContext().getRealPath("/upload");
                    File file = new File(uploadPath,tempFile.getName()); 
                    InputStream is=item.getInputStream();
                    int buffer=1024;                             //定義緩衝區的大小
                    int length=0;
                    byte[] b=new byte[buffer];
                    double percent=0;
                    FileOutputStream fos=new FileOutputStream(file);
                    while((length=is.read(b))!=-1){
                        percent+=length/(double)upFileSize*100D; //計算上傳文件的百分比
                         fos.write(b,0,length);                    //向文件輸出流寫讀取的數據
                        session.setAttribute("progressBar",Math.round(percent)); 
                    }
                    fos.close();
                        Thread.sleep(1000);                         //線程休眠1秒
                } else {
                    error="沒有選擇上傳文件!";
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
        error = "上傳文件出現錯誤:" + e.getMessage();
    }
    if (!"".equals(error)) {
        request.setAttribute("error", error);
        request.getRequestDispatcher("error.jsp").forward(request, response);
    }else {
        request.setAttribute("result", "文件上傳成功!");
        request.getRequestDispatcher("upFile_deal.jsp").forward(request, response);
    }
}

(4)在文件上傳頁index.jsp中,導入編寫的Ajax請求方法的request.js文件,並編寫獲取上傳進度的Ajax請求方法和Ajax回調函數,關鍵代碼以下:

<script language="javascript" src="js/request.js"></script>
<script language="javascript">
var request = false;
function getProgress(){ 
            var url="showProgress.jsp";                         //服務器地址
            var param ="nocache="+new Date().getTime();                  //每次請求URL參數都不一樣 ,避免上傳時進度條不動
            request=httpRequest("post",url,true,callbackFunc,param);   //調用請求方法           
}
//Ajax回調函數
function callbackFunc(){
      if( request.readyState==4 ){               //判斷響應是否完成 
          if( request.status == 200 ){                //判斷響應是否成功
              var h = request.responseText;  //得到返回的響應數據,該數據位上傳進度百分比
           h=h.replace(/\s/g,"");            //去除字符串中的Unicode空白符
                  document.getElementById("progressPercent").style.display="";     //顯示百分比  
                  progressPercent.innerHTML=h+"%";                                  //顯示完成的百分比
                  document.getElementById("progressBar").style.display="block";   //顯示進度條
                  document.getElementById("imgProgress").width=h*(235/100);     //顯示完成的進度
            }
      }
}
</script>

(5)編寫showProgress.jsp頁面,在該頁中應用EL表達式輸出保存在session域中的上傳進度條的值,具體代碼以下:

<%@page contentType="text/html" pageEncoding="GBK"%>
${progressBar}

(6)編寫表單提交按鈕onclick事件所調用的JavaScript方法,在該方法經過window對象的setInterval()方法每隔必定時間請求一次服務器,得到最新的上傳進度,關鍵代碼以下:

function deal(form){
            form.submit();                       //提交表單
            timer=window.setInterval("getProgress()",500);    //每隔500毫秒獲取一次上傳進度
}
相關文章
相關標籤/搜索