struts2文件上传带进度条(一)

实现功能的思路:
1,得到文件上传的进度
2,在页面上显示上传的进度,这就需要不断去读取文件上传的进度
在实现这个功能的时候,首先要认识到,struts2是怎么处理上传的文件的,

struts2也用到了它,那么,到底该怎么找到是哪个类对文件上传进行处理呢?
首先想到的是在配置文件里面找到拦截文件上传的类,在struts2默认的配置文件里,struts2文件上传带进度条(一)_第1张图片
文件上传的处理

type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/>
    type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta-stream" class="org.apache.struts2.dispatcher.multipart.JakartaStreamMultiPartRequest" scope="default"/>
    ```
    ![这是文件上传处理类的位置](http://img.blog.csdn.net/20150601221652534)
    ![这是引入Apache的上传的插件,从这里可以大概知道调用了什么方法](http://img.blog.csdn.net/20150601221820279)
    我们要得到上传的进度条,就需要知道文件上传的监测是在哪个类执行的,初步看了一下,执行文件上传的操作,是在parse这个方法里进行的一些操作,代码如下:

这里写代码片

     * Creates a new request wrapper to handle multi-part data using methods adapted from Jason Pell's
     * multipart classes (see class description).
     *
     * @param saveDir the directory to save off the file
     * @param request the request containing the multipart
     * @throws java.io.IOException is thrown if encoding fails.
     */
    public void parse(HttpServletRequest request, String saveDir) throws IOException {
        try {
            setLocale(request);
            **processUpload(request, saveDir);**
        } catch (FileUploadBase.SizeLimitExceededException e) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("Request exceeded size limit!", e);
            }
            String errorMessage = buildErrorMessage(e, new Object[]{e.getPermittedSize(), e.getActualSize()});
            if (!errors.contains(errorMessage)) {
                errors.add(errorMessage);
            }
        } catch (Exception e) {
            if (LOG.isWarnEnabled()) {
                LOG.warn("Unable to parse request", e);
            }
            String errorMessage = buildErrorMessage(e, new Object[]{});
            if (!errors.contains(errorMessage)) {
                errors.add(errorMessage);
            }
        }
    }

protected List parseRequest(HttpServletRequest servletRequest, String saveDir) throws FileUploadException {
DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
ServletFileUpload upload = createServletFileUpload(fac);
return upload.parseRequest(createRequestContext(servletRequest));
}

加粗的部分跟进去
![发现它是继承FileUpload的](https://img-blog.csdn.net/20150602170626349)
然后再跟进去看,仔细一看,还是没有找到类似于监听文件上传的,然后再找其父类FileUploadBase
当然,这个因为是commons FileUpload的代码,所以还得自己下相应的包,这样才能看到源码

/**
* The progress listener.
*/
private ProgressListener listener;

// ----------------------------------------------------- Property accessors
然后在175行找到这个代码,再跟进去

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the “License”); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.fileupload;

/**
* The {@link ProgressListener} may be used to display a progress bar
* or do stuff like that.
*
* @version Id:ProgressListener.java14546912013030912:15:54Zsimonetripodi
*/
public interface 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);

}


    仔细看这个说明,已经很明显了,这个就是监听文件上传进度的方法,
Apache的命名一般很规范,既然是找监听文件的方法,
那肯定是带有Listen的关键字,所以,在找到这个方法以后,
就可以改写它,让它为我们服务。
    现在,就来写自己的监听类了:

public class FileUploadProgress implements ProgressListener{
@SuppressWarnings(“unused”)
private HttpServletRequest servletRequest;
HttpSession session ;

public FileUploadProgress(HttpServletRequest servletRequest){
    super();
    this.servletRequest = servletRequest;
    session = servletRequest.getSession();
}


/**
 * 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, ...)
 */
public void update(long pBytesRead, long pContentLength, int pItems){
    int pre=0;
    if(pContentLength>-1){
    int current=(int) (pBytesRead*100/pContentLength);
    if(current>pre){
        pre=current;

        session.setAttribute("pre", pre);

    }
    }

}

}

这样,我们就得到了文件上传的进度,并把它放到session当中,
但是,我们得调用它才可以,因为struts2中是没有使用它的,
所以,我们还得把struts2中对文件上传的类进行改写,
我是直接继承,然后覆盖其中对文件上传处理的类JakartaMultiPartRequest

public class JakartaMultiPartRequestEx extends JakartaMultiPartRequest {

@Override
protected List parseRequest(HttpServletRequest servletRequest,
        String saveDir) throws FileUploadException {
    DiskFileItemFactory fac = createDiskFileItemFactory(saveDir);
    ServletFileUpload upload = createServletFileUpload(fac);
    **upload.setProgressListener(new FileUploadProgress(servletRequest));**
    return upload.parseRequest(createRequestContext(servletRequest));
}

}

加粗的部分,就是添加文件上传的监听,
这样,就能够得到文件上传的进度了。
然后就是修改struts配置文件中默认的文件上传处理的类了。

        完成了这些,就基本完成了一半多了,下面再来说一下
只要实现SessionAware这个接口,然后用session去获取就可以了,
但页面怎么接收呢?怎么从action中传到jsp页面当中。
        在这里,我用的是json,就是action中把上传的进度
![这里写图片描述](https://img-blog.csdn.net/20150602172906263)
        然后改一下struts2的配置文件,
在这个插件中,默认是继承struts-default这个包的,
所以,这样并不会影响其他的。
        配置文件代码如下:

        
            209715200
            
        
        
        upload.jsp
        upload.jsp
    

    
    
        percent


        其中,逻辑名为uploadprogress的action,
        是去获取action中的进度的,action的代码如下:

public class FileUploadProgressAction extends ActionSupport implements SessionAware{

private static final long serialVersionUID = 7345654599038757564L;
private Map session;
private int percent;

public int getPercent() {
    return percent;
}

public void setPercent(int percent) {
    this.percent = percent;
}

public Map getSession() {
    return session;
}

@Override
public void setSession(Map session) {
    this.session=session;

}

@Override
public String execute() throws Exception {
    percent=(int) session.get("pre");
    return SUCCESS;
}

}

页面上应该怎么显示出来呢?用进度条的样式,我做的比较简单,
就是通过两个盒子,然后通过宽度的变化来显示进度
,因为可以通过jquery来动态改变盒子的宽度嘛。
脚本代码如下:
//通过ajax请求upload_progress.action获得上传进度[1,2,3,...,100] (function(){ ("#bar").width("0px"); ("#upload").click(function(){
            //提交表单
("form").submit(); //通过代码请求http://localhost:8080/FileUpload/upload_progress.action //定时执行以下代码 window.setInterval(function(){ var url="uploadprogress.action"; .get(url,function(result){
                    //响应成功时执行该函数更新进度条
("#bar").width(result+"px"); //alert(result); /* var url="upload_progress.action"; .get(url,function(result){
                    //响应成功时执行该函数更新进度条
("#bar").width(result); */ }); }, 100); }); });

“`
页面代码如下:
struts2文件上传带进度条(一)_第2张图片
加粗部分就是用来显示进度的,到这里就完成了,样式什么的可以用jquery UI来美化,挺不错的

你可能感兴趣的:(struts2,上传,进度条)