论坛首页 Java企业应用论坛

Java Web开发中上传文件进度条的实现

浏览 14403 次
精华帖 (2) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (10)
作者 正文
   发表时间:2009-06-11  
    今天登陆一个php论坛,发现上传附件时,显示了文件上传的进度条,记起自己以前也研究过在J2EE下上传文件显示进度条的问题,现在整理一下,希望对以后遇到这方面问题的人能够有所帮助。
    获取文件上传的进度主要有二个问题需要解决,一个是上传文件后向服务器获取当前文件传输进度的问题,另一个就是服务器如何计算当前文件的传输进度。
    第一个问题很好解决,通过异步请求不断的向服务器请求文件上传的进度直到文件上传完毕就可以了。主要是如何解决第二个问题。
    现在第三方文件上传的组件很多,如commons-fileupload和cos等,不管用哪一个组件,都是以http协议为基础的,而在Servlet当中,服务器接收的任何数据,都是使用ServletInputStream来读取的,第三方的文件上传组件也是一样的。那么我们可以做一个ServletInputStream的代理类,在读取方法中记录读取数据的字节数,需要注意要区分不同的用户来记录
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的代码
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组件上传文件的代码
HttpServletRequestProxy uploadRequest = new HttpServletRequestProxy(request,observer);
        MultipartRequest multipart = new MultipartRequest(
                uploadRequest,
                webroot,
                sizeLimit,
                new DefaultFileRenamePolicy() 
            );

这样,在上传文件的时候,记录了服务器端获取文件的字节长度,根据上传文件的总长度,就可以计算出文件传输进度的百分比了
   发表时间:2009-06-12  
把代码贴全啊。。。。。。。
1 请登录后投票
   发表时间:2009-06-12  
给个完整的例子啊..谢谢
1 请登录后投票
   发表时间:2009-06-12  
markUploadSize这方法在哪呢
1 请登录后投票
   发表时间:2009-06-12  
So懒 写道
    今天登陆一个php论坛,发现上传附件时,显示了文件上传的进度条,记起自己以前也研究过在J2EE下上传文件显示进度条的问题,现在整理一下,希望对以后遇到这方面问题的人能够有所帮助。
    获取文件上传的进度主要有二个问题需要解决,一个是上传文件后向服务器获取当前文件传输进度的问题,另一个就是服务器如何计算当前文件的传输进度。
    第一个问题很好解决,通过异步请求不断的向服务器请求文件上传的进度直到文件上传完毕就可以了。主要是如何解决第二个问题。
    现在第三方文件上传的组件很多,如commons-fileupload和cos等,不管用哪一个组件,都是以http协议为基础的,而在Servlet当中,服务器接收的任何数据,都是使用ServletInputStream来读取的,第三方的文件上传组件也是一样的。那么我们可以做一个ServletInputStream的代理类,在读取方法中记录读取数据的字节数,需要注意要区分不同的用户来记录
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的代码
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组件上传文件的代码
HttpServletRequestProxy uploadRequest = new HttpServletRequestProxy(request,observer);
        MultipartRequest multipart = new MultipartRequest(
                uploadRequest,
                webroot,
                sizeLimit,
                new DefaultFileRenamePolicy() 
            );

这样,在上传文件的时候,记录了服务器端获取文件的字节长度,根据上传文件的总长度,就可以计算出文件传输进度的百分比了


一个是上传文件后向服务器获取当前文件传输进度的问题
另一个就是服务器如何计算当前文件的传输进度。

服务器怎么提供给你上传进度? 流在传输的时候有异步返回进度的API?

这样,在上传文件的时候,记录了服务器端获取文件的字节长度,根据上传文件的总长度,就可以计算出文件传输进度的百分比

还是这个问题,等你计算了文件大小说明文件都已经进入流了 也就是说上传完毕了.得到大小还有意义吗?

希望你把代码完整的贴出来而不是贴些乱七八糟的东西


2 请登录后投票
   发表时间:2009-06-12  
楼主给个完整的代码吧
1 请登录后投票
   发表时间:2009-06-13  
现在计算进度速度之类都是在客户端计算的,,无需通过服务器。。

在客户端和在服务器计算是一样的
1 请登录后投票
   发表时间:2009-08-12  
willko 写道
现在计算进度速度之类都是在客户端计算的,,无需通过服务器。。

在客户端和在服务器计算是一样的


还得请教
1、客户端(浏览器端)如何直接计算进度?
2、服务器端有没有对上传的文件流进行监听并与客户端进行交互的API? 通过异步来处理的话也只能对正在写的文件进行处理吧。而且实现这个之前要知道文件的存储路径。
0 请登录后投票
   发表时间:2009-08-13  
_咖啡杯垫 写道
willko 写道
现在计算进度速度之类都是在客户端计算的,,无需通过服务器。。

在客户端和在服务器计算是一样的


还得请教
1、客户端(浏览器端)如何直接计算进度?
2、服务器端有没有对上传的文件流进行监听并与客户端进行交互的API? 通过异步来处理的话也只能对正在写的文件进行处理吧。而且实现这个之前要知道文件的存储路径。

无非是flash或activex、Silverlight

js是没办法的
1 请登录后投票
   发表时间:2009-11-01  
现在计算进度速度之类都是在客户端计算的,,无需通过服务器。。

0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics