今天登陆一个php论坛,发现上传附件时,显示了文件上传的进度条,记起自己以前也研究过在J2EE下上传文件显示进度条的问题,现在整理一下,希望对以后遇到这方面问题的人能够有所帮助。
获取文件上传的进度主要有二个问题需要解决,一个是上传文件后向服务器获取当前文件传输进度的问题,另一个就是服务器如何计算当前文件的传输进度。
第一个问题很好解决,通过异步请求不断的向服务器请求文件上传的进度直到文件上传完毕就可以了。主要是如何解决第二个问题。
现在第三方文件上传的组件很多,如commons-fileupload和cos等,不管用哪一个组件,都是以http协议为基础的,而在Servlet当中,服务器接收的任何数据,都是使用ServletInputStream来读取的,第三方的文件上传组件也是一样的。那么我们可以做一个ServletInputStream的代理类,在读取方法中记录读取数据的字节数,需要注意要区分不同的用户来记录
Java代码
通过上面的代码,我们可以在文件上传的时候,通过代理的ServletInputStream来记录服务器端读取到的文件字节数,但只代理ServletInputStream还不行,因为ServletInputStream是由HttpServletRequest获取的,所以我们还需要代理HttpServletRequest,这里可以用动态代理或者代理HttpServletRequestWrapper,下面给出代理HttpServletRequestWrapper的代码
Java代码
之后我们在使用第三方组件上传文件的时候,需要用HttpServletRequestProxy代替HttpServletRequest
下面是使用cos组件上传文件的代码
Java代码
这样,在上传文件的时候,记录了服务器端获取文件的字节长度,根据上传文件的总长度,就可以计算出文件传输进度的百分比了
获取文件上传的进度主要有二个问题需要解决,一个是上传文件后向服务器获取当前文件传输进度的问题,另一个就是服务器如何计算当前文件的传输进度。
第一个问题很好解决,通过异步请求不断的向服务器请求文件上传的进度直到文件上传完毕就可以了。主要是如何解决第二个问题。
现在第三方文件上传的组件很多,如commons-fileupload和cos等,不管用哪一个组件,都是以http协议为基础的,而在Servlet当中,服务器接收的任何数据,都是使用ServletInputStream来读取的,第三方的文件上传组件也是一样的。那么我们可以做一个ServletInputStream的代理类,在读取方法中记录读取数据的字节数,需要注意要区分不同的用户来记录
Java代码
public ServletInputStreamProxy(ServletInputStream in,
UploadFileObserver observer) {
this.in = in;
this.observer = observer;
}
public int read(byte[] b, int off, int len) throws IOException {
int r = in.read(b, off, len);
if (r != -1) {
observer.markUploadSize(r);
}
return r;
}
通过上面的代码,我们可以在文件上传的时候,通过代理的ServletInputStream来记录服务器端读取到的文件字节数,但只代理ServletInputStream还不行,因为ServletInputStream是由HttpServletRequest获取的,所以我们还需要代理HttpServletRequest,这里可以用动态代理或者代理HttpServletRequestWrapper,下面给出代理HttpServletRequestWrapper的代码
Java代码
public class HttpServletRequestProxy extends HttpServletRequestWrapper {
private UploadFileObserver observer;
public HttpServletRequestProxy(HttpServletRequest request,UploadFileObserver observer) {
super(request);
this.observer = observer;
}
/* (non-Javadoc)
* @see javax.servlet.ServletRequestWrapper#getInputStream()
*/
public ServletInputStream getInputStream() throws IOException {
ServletInputStream in = super.getInputStream();
return new ServletInputStreamProxy(in,observer);
}
}
之后我们在使用第三方组件上传文件的时候,需要用HttpServletRequestProxy代替HttpServletRequest
下面是使用cos组件上传文件的代码
Java代码
HttpServletRequestProxy uploadRequest = new HttpServletRequestProxy(request,observer);
MultipartRequest multipart = new MultipartRequest(
uploadRequest,
webroot,
sizeLimit,
new DefaultFileRenamePolicy()
);
这样,在上传文件的时候,记录了服务器端获取文件的字节长度,根据上传文件的总长度,就可以计算出文件传输进度的百分比了