您的位置:首页 > 编程语言 > Java开发

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

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


struts2也用到了它,那么,到底该怎么找到是哪个类对文件上传进行处理呢?

首先想到的是在配置文件里面找到拦截文件上传的类,在struts2默认的配置文件里,




<bean type="org.apache.struts2.dispatcher.multipart.MultiPartRequest" name="jakarta" class="org.apache.struts2.dispatcher.multipart.JakartaMultiPartRequest" scope="default"/>
<bean 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.java14546912013−03−0912: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<FileItem> parseRequest(HttpServletRequest servletRequest,
String saveDir) throws FileUploadException {
DiskFileItemFactory fac = createDiskFileItemFactory(save
a8ea
Dir);
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这个包的,
所以,这样并不会影响其他的。
配置文件代码如下:


<interceptor-ref name="fileUpload">
<param name="maximumSize">209715200</param>
<!-- <param name="allowedTypes">image/jpeg,image/gif</param> -->
</interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result name="input">upload.jsp</result>
<result>upload.jsp</result>
</action>

<action name="uploadprogress" class="com.jxnuss.net.x3516.actions.FileUploadProgressAction">
<result type="json">
<param name="root">percent</param>


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


public class FileUploadProgressAction extends ActionSupport implements SessionAware{

private static final long serialVersionUID = 7345654599038757564L;
private Map<String, Object> session;
private int percent;

public int getPercent() {
return percent;
}

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

public Map<String, Object> getSession() {
return session;
}

@Override
public void setSession(Map<String, Object> 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);
});
});

“`

页面代码如下:



加粗部分就是用来显示进度的,到这里就完成了,样式什么的可以用jquery UI来美化,挺不错的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: