为Web文件上传添加进度条

Web形式的文件上传向来是友好的, 进度难以确定。 以前一些办法是使用meta fresh定时刷新页面来查询

上传进度, 刷屏刷IFRAME之类的页面闪烁.
用Ajax来定时查询进度,  页面的效果就好多了. 但是苦的就是一堆的JS了。

Java为例, Apache commons file upload组件, 可能是在1.0的版本之后添加了一个支持处理进度的回调

接口,org.apache.commons.fileupload.ProgressListener

    /** Updates the listeners status information.
     * @param pBytesRead The total number of bytes, which have been read
     *   so far.
     * @param pContentLength The total number of bytes, which are being
     *   read. May be -1, if this number is unknown.
     * @param pItems The number of the field, which is currently being
     *   read. (0 = no item so far, 1 = first item is being read, ...)
     */
    void update(long pBytesRead, long pContentLength, int pItems);

如果FileUpload设置了ProgressListener的话,上传每读取若干个字节都会调用这个方法。
可以把这些文件总长,读取总字节数有用信息放在session里面,等前台Ajax call来查询这个状态.

以Spring MVC为例:

<!--CommonsMultipartResolver to upload file  -->
<bean id="multipartResolver" class="com.xxxxx.web.MonitoredCommonsMultipartResolver">
     <!-- <property name="maxUploadSize"><value>52428800</value></property> -->
</bean>

public class MonitoredCommonsMultipartResolver extends CommonsMultipartResolver {
    /**
     * Add ProgressListener
     * resolveMultipart
     * @see org.springframework.web.multipart.commons.CommonsMultipartResolver#resolveMultipart(javax.servlet.http.HttpServletRequest)
     */
    public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        String encoding = determineEncoding(request);
        FileUpload fileUpload = prepareFileUpload(encoding);
        ProgressListener pListener = new DefaultProgressListener(request);
        fileUpload.setProgressListener(pListener);
        try {
            List fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
            MultipartParsingResult parsingResult = parseFileItems(fileItems, encoding);
            return new DefaultMultipartHttpServletRequest(
                    request, parsingResult.getMultipartFiles(), parsingResult.getMultipartParameters());
        }
        catch (FileUploadBase.SizeLimitExceededException ex) {
            throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
        }
        catch (FileUploadException ex) {
            throw new MultipartException("Could not parse multipart servlet request", ex);
        }
    }

}


public class DefaultProgressListener implements ProgressListener {
    
    private static final Log log = LogFactory.getLog(DefaultProgressListener.class);
    
    
    
    private HttpSession session = null;
    
    public DefaultProgressListener(){
    }
    
    public DefaultProgressListener(HttpServletRequest request){
        this.session = request.getSession(false);
        MultipartFileStatus multipartFileStatus = new MultipartFileStatus();
        session.setAttribute(Constants.MULTIPART_FILE_STATUS, multipartFileStatus);
    }
    
    
    

    /**
     * update
     * @see org.apache.commons.fileupload.ProgressListener#update(long, long, int)
     */
    public void update(long bytesRead, long contentLength, int items) {
        if (log.isDebugEnabled())
            log.debug("bytesRead=" + bytesRead + ",contentLength=" + contentLength + ",items=" + items);

        MultipartFileStatus multipartFileStatus = (MultipartFileStatus)
            session.getAttribute(Constants.MULTIPART_FILE_STATUS);
        multipartFileStatus.setStatus(bytesRead, contentLength);
    }

}




public class MultipartFileStatus {
    
    private long contentLength = 0;
    
    private long bytesRead = 0;
    
    public MultipartFileStatus() {
    }

    /**
     * @return the contentLength
     */
    public long getContentLength() {
        return contentLength;
    }

    /**
     * @param contentLength the contentLength to set
     */
    public void setContentLength(long contentLength) {
        this.contentLength = contentLength;
    }

    /**
     * @return the bytesRead
     */
    public long getBytesRead() {
        return bytesRead;
    }

    /**
     * @param bytesRead the bytesRead to set
     */
    public void setBytesRead(long bytesRead) {
        this.bytesRead = bytesRead;
    }
    
    /**
     *
     * @param pBytesRead
     * @param pContentLength
     */
    public void setStatus(long pBytesRead, long pContentLength) {
        this.bytesRead = pBytesRead;
        this.contentLength = pContentLength;
    }
    
    /**
     * Return Json style string
     * @return
     */
    public String getJsonStyleStatus() {
        StringBuffer buf = new StringBuffer();
        buf.append("{bytesRead:").append(this.bytesRead).
            append(",contentLength:").append(this.contentLength).append('}');
        return buf.toString();
    }
    
    

}


<script type="text/javascript">

    //Set the mainForm property
    var mainForm=Ext.getDom('mainForm');
    mainForm.enctype='multipart/form-data';

    //==== Progress bar ====
    var uploadProgressBar = new Ext.ProgressBar({
       text:'Uploading ...'
    });


Ext.onReady(function(){
});

    //Start upload
    function startUpload() {
        
        //FIXME add validation later.
        Ext.Ajax.timeout = 1000*3600;
        Ext.Ajax.request({
                method:'post',
                form: 'mainForm',
                params:'method=upload',
                url: 'uploadImageHandler.html',
                success: uploadSuccess,
                failure: uploadFail
        });
        if (!uploadProgressBar.rendered) uploadProgressBar.render('uploadProgressBarContainer');
        uploadProgressBar.updateProgress(0,'Start uploading...');
        //Start Timer thread
        Ext.TaskMgr.start({
            run:function(){
                Ext.Ajax.request({
                    method:'post',
                    params:'method=queryStatus',
                    url: 'uploadImageHandler.html',
                    success: queryUploadSuccess,
                    failure: queryUploadFail
                });
            },
            interval: 1000
        });
        
    }
    function uploadSuccess(response){
        alert(response.responseText + " upload  is successful!");
    }
    function uploadFail(response) {
        alert("Upload image is failed.");
        Ext.TaskMgr.stopAll();
    }
    function queryUploadSuccess(response) {
        //alert(response.responseText + " query success!");
        var fileStatus = Ext.decode(response.responseText);
        var percentage=fileStatus.bytesRead/fileStatus.contentLength;
        uploadProgressBar.updateProgress(percentage, (percentage * 100) + "%");
        if (percentage == 1)
          Ext.TaskMgr.stopAll();
    }
    function queryUploadFail(response) {
        alert("Ajax call query status fails!");
        Ext.TaskMgr.stopAll();
    }
</script>

很粗的一个测试例子, 好好完善Cancel之类的按钮也是可以加上去的。网上也有很多相似的文章, 本文主要是
在Spring MVC那个专有些, 使用Ext 1.1.1 + 2.0的progress bar widget, 做页面是个苦事.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值