Ajax上传文件和真实进度条实现原理
ajax文件上传:
很多时候,上传文件都只是一个小页面中的一个功能,要求在实现文件上传的前提下不刷新页面。而一般情况下将客户端的文件包装成网络地址传递到服务器端然后通过流来进行文件传输的任务都是使用浏览器来帮我们完成的,而且似乎我们非常难以插手进去。对于普通的form字段,我们可以手动拿到其中的值,然后封装成一个请求数据传输的对象,然后发出ajax请求,就可以将我们客户端的数据传递到后台去。但是file控件却不行,为了安全着想,js是不允许访问客户端的文件系统的(某些比较具有影响力的公司可能会开发出浏览器的插件,使得可以访问客户端的文件系统)。所以我们无法拿到文件控件的数据,所以具体的传输操作还要请求浏览器来帮我们完成。所以为了实现ajax来上传文件的效果,是有一些困难的,所以人们就想到了一种折衷的方案,就是在页面中的一个小区域中添加一个iframe对象,然后引用到另外一个页面中,然后再我们上传文件的时候只需要提交该页面即可,并不会导致主页面提交,这样就模拟出了一种ajax上传文件的方式。
ajax进度条:
想要实现进度条效果,也许比实现仿ajax文件上传要来的更麻烦。在网上有很多ajax进度条的源码,实现的方式也是各种各样,良莠不齐。其中更有很多的实现方式虽然展现出了进度条的效果,但是却和文件上传的进度没有一点的关系。我还看见过一个这样的例子,在一个页面中添加了一个file控件和一个submit控件。然后在下面有一个table用来实现进度条的效果。在点击提交的时候他会触发一个onclick事件,在这个事件里面他采用了定时器一点点的用颜色去填充table中的进度条。当进度条填充完毕了之后(也就是意味着文件上传完成),然后提交form,在进度条上展示已经上传完成,可是真正的上传才随着页面的提交刚刚开始。
对于这个ajax进度条的实现看到了几种解决方案:
1.flash和sliverlight,不知道具体实现细节,有明白的大侠请拍砖。感激不尽!
2.struts2(伪进度):用struts2来实现文件上传的方式就是我们在后台会拿到一个已经被封装好的File对象,然后把file对象包装成一个输入流,然后在服务器端文件系统中新建一个文件,将该文件包装成输入流,然后不断从输入流中读取字节转到输出流中,这个过程是一个持续的过程。中间使用缓冲区来进行字节数据的中转,而且每一次中转的字节数都可以拿到,就想着如果在这个过程中把已经传输的哦写入到本地文件系统中的字节数记录下来不久意味着已经传递了多少字节数,即传输的文件长度,而且文件的总长度也可以很方便的获取。然后将这个信息保存在session里面,再在客户端不断的发ajax请求从里面拿到这个值,然后再客户端将该值展示出来即可。但是事实并非如此,其实在我们在后台的上传文件的action代码中的时候,文件已经上传好了,是由sturts2已经帮我们将客户端上传的文件都已经传输完毕,保存在服务器端的内存系统或者是一个临时的文件中。然后我们所执行的数据传输其实只是从服务器端的内存系统或临时文件系统转到我们规定的一个文件中去。
3.servlet添加监听器
还有一种方式就是放弃使用struts2来帮助我们上传文件,使用servlet来完成文件上传。然后在上传的action中添加进度条监视器,因为在传输的工程中监视器可以获取上传的大小信息和文件总大小信息。然后将这些信息保存在session里面或者是一个工厂里面,然后也再客户端不断的发出请求,来获取进度信息并进行展示