实现功能的思路:
1,得到文件上传的进度
2,在页面上显示上传的进度,这就需要不断去读取文件上传的进度
在实现这个功能的时候,首先要认识到,struts2是怎么处理上传的文件的,
struts2也用到了它,那么,到底该怎么找到是哪个类对文件上传进行处理呢?
首先想到的是在配置文件里面找到拦截文件上传的类,在struts2默认的配置文件里,
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.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 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(){