廣告贊助

出處: http://blog.yslifes.com/archives/908

 

=============================

 

 

之前寫過一個jsp的檔案上傳,把檔案上傳的動作製成一個class。而現在要提供的這個範例就比較亂一點了,重點會在增加監控的ProgressListener及Ajax取得上傳進度之資料。

程式需要一個bean放入session裡,專門來存放目前上傳的bytes數及其它資訊,選擇好檔案按下上傳時,會開始上傳動作(使用iframe),並啟動Ajax與Server要求目前上傳進度狀況,把資訊顯示在browser上。

FileUpload2.jpg

 

這個專案需要使用二個額外的jar framework,分別為Apache FiluploadApache common io,而Fileupload需要1.2以上版本才支援ProgressListener。

存入上傳資訊的bean

package com.yslifes.file.upload;
 
public class UploadStatus {
    private long bytesRead;// 目前上傳byte數
    private long totBytes;// 總共的byte數
    private int item;// 目前上傳的item
    private long startTime;// 啟始時間
 
    public UploadStatus() {
        startTime = System.currentTimeMillis();
    }
 
    public long getBytesRead() {
        return bytesRead;
    }
 
    public void setBytesRead(long bytesRead) {
        this.bytesRead = bytesRead;
    }
 
    public long getTotBytes() {
        return totBytes;
    }
 
    public void setTotBytes(long totBytes) {
        this.totBytes = totBytes;
    }
 
    public int getItem() {
        return item;
    }
 
    public void setItem(int item) {
        this.item = item;
    }
 
    public long getStartTime() {
        return startTime;
    }
 
    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
 
}

監控的ProgressListener

在上傳時,會一直呼叫ProgressListener的update函數。

package com.yslifes.file.upload;
 
import org.apache.commons.fileupload.ProgressListener;
 
public class UploadListener implements ProgressListener {
    // 存放upload狀態的bean
    private UploadStatus status;
 
    public UploadListener(UploadStatus status) {
        this.status = status;
    }
 
    // override,上傳時會被呼叫
    @Override
    public void update(long arg0, long arg1, int arg2) {
 
        status.setBytesRead(arg0);// 目前已上傳的byte數
        status.setTotBytes(arg1);// 總byte數
        status.setItem(arg2);// 正在上傳的item編號
    }
 
}

上傳畫面html

onsubmit時順便啟動Ajax動作來監控上傳進度,而ProgressBar則是由取得的資料利用css的width來設定目前上傳量。

<body>
 
<form action="UploadAction.jsp" method="post"
    enctype="multipart/form-data" target="hiddenFrame"
    onsubmit="showStatus()">
<div align="center">
<table>
    <tr>
        <td>上傳檔案1</td>
        <td><input type="file" name="file1" /></td>
        <td>描述1</td>
        <td><input type="text" name="desc1" /></td>
    </tr>
    <tr>
        <td>上傳檔案2</td>
        <td><input type="file" name="file2" /></td>
        <td>描述2</td>
        <td><input type="text" name="desc2" /></td>
    </tr>
    <tr>
        <td colspan="4" align="left"><input id="button" type="submit"
            name="submit" value="確認" /></td>
    </tr>
</table>
<div id="status" style="display: none" align="left">
<div id="progressBar"
    style="width: 400px; height: 12px; background: #fff; border: 1px solid #00ff00; padding: 3px;">
<div id="barItem" style="width: 30%; height: 100%; background: #ff0000"></div>
</div>
<div id="msg"></div>
</div>
</div>
</form>
 
<iframe name="hiddenFrame" width="0" height="0" frameborder="0"></iframe>
</body>

Ajax的javascript內容

reuqest取得資料後,如果還沒上傳完成,則再利用setTimeout,一秒後重新再要求資料。

var success = true;//完成上傳與否
    //取得上傳資訊
    function showStatus() {
        success = false;
        //顯示ProgressBar
        document.getElementById("status").style.display = "block";
        //初始1%
        document.getElementById("barItem").style.width = '1%';
        //上傳按鈕使不能使用
        document.getElementById("button").disabled = true;
        //一秒檢查一次上傳狀態
        setTimeout("requestStatus()", 1000);
    }
    function requestStatus() {
        if (!success) {
            var ajax;
            if (window.XMLHttpRequest)//ajax request Object,非ie
                ajax = new XMLHttpRequest();
            else//ie
            {
                try {
                    ajax = new ActiveXObject("Mxsml2.XMLHTTP");
                } catch (e) {
                    ajax = new ActiveXObject("Microsoft.XMLHTTP");
                }
            }
 
            ajax.open("GET", "UploadStatus.jsp");
            ajax.onreadystatechange = function() {
                callback(ajax);
 
            };
            ajax.send(null);
 
        }
    }
 
    function callback(ajax) {
        if (ajax.readyState == 4) {
            if (ajax.status != 200)//有錯誤產生
            {
                document.getElementById("msg").innerHTML = "回傳錯誤!";
            } else {
                var arr = ajax.responseText.split("/");
                if (arr.length < 2) {
                    document.getElementById("msg").innerHTML = ajax.responseText;
                } else {
                    //進度
                    document.getElementById("barItem").style.width = ""
                            + arr[0] + "%";
                    document.getElementById("msg").innerHTML = '完成百分比(%):'
                            + arr[0] + '</br>'+
                    '已完成數(M):' + arr[1] + '</br>'+
                    '檔案總長度(M):' + arr[2] + '</br>'+
                    '傳輸速率(K):' + arr[3] + '</br>'+
                    '已使用時間(s):' + arr[4] + '</br>'+
                    '估計總時間(s):' + arr[5] + '</br>'+
                    '估計剩餘時間(s):' + arr[6] + '</br>'+
                    '正在上傳文件:' + arr[7];
 
                    if (arr[1] == arr[2]) {
                        success = true;
                        document.getElementById("msg").innerHTML = "完成上傳!";
                        //把上傳按鈕設可使用
                        document.getElementById("button").disabled = false;
 
                    }else
                        setTimeout("requestStatus()", 1000);
                }
            }
        }
    }

上傳動作

因為在form表單時已經設定target為iframe,所以並不會把目前頁面帶離,只會在iframe裡進行上傳動作,而iframe本身設定為看不到。

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%><%
    com.yslifes.file.upload.UploadStatus status = new com.yslifes.file.upload.UploadStatus();
    com.yslifes.file.upload.UploadListener listener = new com.yslifes.file.upload.UploadListener(status);
 
    //放到session裡
    //再來listener就會依上傳狀況去更動status了
    session.setAttribute("status",status);
 
    org.apache.commons.fileupload.servlet.ServletFileUpload upload = new org.apache.commons.fileupload.servlet.ServletFileUpload(new org.apache.commons.fileupload.disk.DiskFileItemFactory());
    upload.setProgressListener(listener);//設定監控
 
    try
    {
        java.util.List<org.apache.commons.fileupload.FileItem> items = upload.parseRequest(request);//把request parse成FileItem List
        java.util.Iterator<org.apache.commons.fileupload.FileItem> it = items.iterator();
        while(it.hasNext())
        {
            org.apache.commons.fileupload.FileItem item = it.next();
            if(item.isFormField())//一般的表單資料
            {
                System.out.println("表單資料名稱:"+item.getFieldName()+",表單資料內容:"+item.getString());
 
            }else//檔案上傳
            {
                System.out.println("檔案名稱:"+item.getName());
                String fileName = item.getName();
 
                //要存放檔案的路徑及目錄
                java.io.File saveFile = new java.io.File("./upload",fileName);
                //如果目錄不存在.則會自動建立
                saveFile.getParentFile().mkdirs();
 
                //讀出輸入串流
                java.io.InputStream in = item.getInputStream();
 
                //寫入輸出串流
                java.io.OutputStream writer = new java.io.FileOutputStream(saveFile);
 
 
                //寫入檔案
                byte[] tmp = new byte[1024];
                int len ;
                while((len=in.read(tmp))!=-1)
                {
                    writer.write(tmp,0,len);
                }
 
                writer.close();
                in.close();
                out.write("上傳成功!");
            }
        }
 
 
    }catch(org.apache.commons.fileupload.FileUploadException e)
    {
        e.printStackTrace();
        out.println("上傳時發生錯誤:"+e);
    }
 
 
    %>

取得監控的上傳資料

利用ajax要求這個程式來取得目前上傳的進度

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="BIG5"%>
<%
    //不讓browser使用cache資料
    response.setHeader("Cache-Control", "on-store");
    response.setHeader("Pagrma", "no-cache");
    response.setDateHeader("Expires", 0);
 
    //從session裡把資料取出來
    com.yslifes.file.upload.UploadStatus status = (com.yslifes.file.upload.UploadStatus) session
            .getAttribute("status");
 
    if (status == null) {
        out.println("未有上傳資料");
    } else {
        long startTime = status.getStartTime();
        long nowTime = System.currentTimeMillis();
        long time = (nowTime - startTime) / 1000 + 1;//上傳時間秒
 
        //總共的上傳資料bytes
        double totalLength = status.getTotBytes();
 
        //上傳送率 byte/s
        double velocity = status.getBytesRead() / (double) time;
 
        //估計總時間秒
        double totalTime = totalLength / velocity;
        //估計剩飲時間秒
        double guessTime = totalTime - time;
 
        //完成百分比
        int percent = (int) Math.round((100 * (double) status
                .getBytesRead()) / totalLength);
        //已讀取Mb數
        double M_Readlength = (double) status.getBytesRead() / 1024 / 1024;
        //總Mb數
        double m_TotalLength = (double) totalLength / 1024 / 1024;
 
        out.print(percent + "/");
        out.print(M_Readlength + "/");
        out.print(m_TotalLength + "/");
        out.print(velocity + "/");
        out.print(time + "/");
        out.print(totalTime + "/");
        out.print(guessTime + "/");
        out.print(status.getItem());
 
    }
%>

執行畫面,一開始狀況及按下確認後畫面

FileUpload1.jpg

FileUpload2.jpg

原始碼下載

創作者介紹
創作者 瑞、瑪姬與小昆妮 的頭像
瑞、瑪姬與小昆妮

瑞瑪姬與小昆妮♫趴趴走黑白吃

瑞、瑪姬與小昆妮 發表在 痞客邦 留言(0) 人氣()