关闭

stream插件跨域大文件断点续传实战+自定义限速

标签: ssh断点续传大文件上传stream
1757人阅读 评论(3) 收藏 举报
分类:
JAVA跨域大文件断点续传+自定义限速

前言:本文所讲到的内容完全独创,遇坑很多,但是本着资源共享的原则,将两个星期的成果分享给大家,请尊重别人的劳动成果,转载请注明出处:http://blog.csdn.net/qq_27063119,谢谢!

先讲述一下本文所针对的问题:
1.跨域,所谓跨域就是就是服务器之间的分离,如,一个系统中,应用程序为在一个服务器上,而应用程序往往需要上传文件,将上传文件作为独立的一个功能放在另外的一台服务器上,这时上传文件就是跨域了,若将上传文件部分也放在应用服务器上,一旦流量过大,服务器瘫痪,那么会导致主应用程序也不能够使用。

2.大文件断点续传 , 这是基于HTML5标准,因此IE9(包括IE9)以下浏览器不支持,为了兼容了IE6以上的浏览器上传,只能选择使用flash进行上传,但是此时不可以断点续传。

3.自定义限制文件上传的速度  ,对源码进行修改时的支持自定义限速功能。


(第一种)以下为简单整合上传的方法(不跨域可以使用):
    这里我们借助了stream上传插件,这是官网:http://www.twinkling.cn  ,然后点击下载页,通过开源中国或者百度云盘下载官方的实例1.8.1.xxx,需要下载stream-1.8.1.10157.war,以及stream-1.8.0.10076-r.jar,官方的JAVA后台代码jiangdx-stream-master.zip只有从开源中国上面下载,准备好这两个文件就可以了,开始整合操作:
(1).解压jiangdx-stream-master.zip文件后,将jiangdx-stream-master\stream\src\main文件夹下的java目录整个拷贝到你的项目src中。

(2)解压stream-1.8.1.10157.war后,打开文件夹,将除了META-INF ,WEB-INF不拷贝其他全部拷贝到自己工程项目的WEB-INF目录下.

(3).添加jar包,将stream-1.8.1.10157\WEB-INF\lib 下的所有jar包以及stream-1.8.0.10076-r.jar,json-20090211.jar拷贝放置到自己工程的lib下
    到这里基本最简单的文件上传就搭建好了,打开tomcat服务器,浏览器输入地址,http://127.0.0.1:8080/stream/index.html,进入上传页面,即可进行文件上传,这是官方的指导方法,实际上按照上面的做法并不能进行上传,至少IE还是不能进行上传,这里说一下解决的方法:
  a:    修改url地址
swfURL : "/swf/FlashUploader.swf", 改为相对地址:swfURL : "swf/FlashUploader.swf", 
tokenURL : "/tk",改为相对地址:tokenURL : "tk",
frmUploadURL : "/fd", 改为相对地址:frmUploadURL : "fd",
uploadURL : "/upload", 改为相对地址:uploadURL : "upload",
 
  b:   最后一个参数结尾不要加逗号
     var config = {
    .....第一个参数......,
    ......第二个参数..... ,
    ......第N个参数......
}
注意最后一个参数不要以,号结尾,否则IE下就不能执行了。
以上修改好后即可进行上传操作,文件保存的路径在 stream-config.properties 配置中。

  虽然以上配置好了可以进行上传操作,但是远远不能满足公司实际使用的要求,比如防止文件冲突,对上传的文件进行重命名操作同时保存实际文件名至数据库,配置数据库连接池,上传限速,应用上传分离中的跨域上传,于是这里是本人原创的做法,不一定就是最好的,但是可以借鉴使用。 这里采用了spring MVC  + spring  + hibernate  + stream插件进行整合在一起。

(第二种 )修改后具有的特点:SSH框架整合,文件防冲突,回传文件信息至前台,上传界面美化,上传限速,跨域上传,兼容IE6-IE9 :

为了让大家更好的了解这个上传问题,这里贴出了我的代码地址:http://download.csdn.net/detail/qq_27063119/9630240  (6个金币下载,大家支持一下好吧,打这么多字不容易啊,实在没有金币就  至我邮件  nuohy@qq.com(不一定能够及时回复,请谅解!))

(1)首先还是搭建好上传文件的项目以支持跨域上传,使用spring MVC+spring+hibernate的框架,以及一个测试的项目(随便用什么搭建,建议使用最简单的jsp+servlet),搭建完毕后,效果是,启动两个项目,当然两个项目可以放置到两台机器上,只要两台机器可以ping通就可以,

streamSH项目结构如图所示:




ceshi项目结构如图所示:



看了上面的结构,大家应该有所了解了吧,其中streamSH中的TokenController可以去掉,因为跨域上传,token码是由应用服务器生成的,所以要放到ceshi项目中。当然stream有自己的配置文件文档上说可以进行跨域上传,但是我试了好久发现不好用,于是自己改写了,在streamSH项目上加了过滤器进行添加头信息

public class SecurityFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request,HttpServletResponse response, FilterChain chain)throws ServletException, IOException {
System.out.println("********************跨域**********************");
System.out.println("=========="+request.getMethod()+"============"+request.getHeader("Access-Control-Request-Method"));
if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
System.out.println("===================添加头文件===================");
response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
            response.addHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
            response.addHeader("Access-Control-Max-Age", "1800");//30 min
        }
chain.doFilter(request, response);
    }
}



并且每个controller都会对request以及response进行添加头信息 即在controller中调用doOptions()方法

@RequestMapping(method=RequestMethod.GET,value="/upload")
	public void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException{
	doOptions(req, resp);
	.
	.
	.
}


protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws UnsupportedEncodingException{
	req.setCharacterEncoding("UTF-8");
	resp.setCharacterEncoding("UTF-8");
	resp.setContentType("application/json;charset=utf-8");
	resp.setHeader("Access-Control-Allow-Origin", "*");
	resp.setHeader("Access-Control-Allow-Headers", "Content-Range,Content-Type");
	resp.setHeader("Access-Control-Allow-Origin", Configurations.getCrossOrigins());
	resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS");
}



(2)上传界面美化,如下图所示,这里我改动了js以及css样式以及iframe的界面,具体可以参考我的代码,



 这里顺带提一下,测试跨域上传时候,如果两个项目放在本机同一个服务器下,建议使用http://127.0.0.1:8080 开头或者  http://localhost:8080,不然即使不能够跨域上传,但是测试不出来,

(3)上传限速问题
      其实限速原理很简单,也就是while循环写入数据时候,加上Thread.sleep(XXX);就达到了限速目的,这里我在配置文件中加了一句   STREAM_UPLOAD_SPEED=1500   (及1.5MB/S),  后台拿到这个数据后,需要进行操作,
 真正的休眠时间为:7500/(STREAM_UPLOAD_SPEED数字);   这个是我的机器测试测出来的,可以自行计算填写的,然后flax上传时,休眠时间为  (7500/(STREAM_UPLOAD_SPEED数字))/2,不要问为什么,我也是测出来的。

(4)兼容IE6-IE9
    为了兼容IE6-IE9,需要使用flash进行上传,当然不跨域时候比较容易的,跨域了,就会麻烦,比如:IE7跨域上传时候,tolenURL  必须为应用服务器的controller或者servlet的地址,否则上传不了,这里弄好了过后,你会发现还是上传不了的,因为flash跨域时候会请求跨域服务器的crossdomain.xml文件,这个文件要放到 tomcat的根目录下,也就是webapps\ROOT目录下,如果发现没有这个目录,那你应该是使用myeclipse了,这里举个例子:放到workspace\.metadata\.me_tcat7\webapps目录下  ,然后在server.xml的<Host></Host>中添加
<Context path="" docBase="D:\\myeclipse\\workspace\\.metadata\\.me_tcat7\\webapps\\" reloadable="true"  />
这样一段话即可,  不管你怎样弄,只要能够使保证用文件服务器的地址 加上crossdomain.xml,如http://192.168.1.141:8080/crossdomain.xml 能够访问到文件就可以了。这里一定要注意啊!!!!!



(5)文件防止冲突
因为用户上传的文件可能会重名,那么直接存储会导致覆盖文件,为了避免文件上传的冲突,于是我们要使用UUID对文件进行重新命名,并且将文件的真实名字以及UUID,文件路径都存储到数据库中,同时将UUID 以及 文件真实的名字 回传到前台,前台接受数据 通过
onComplete : function(file) {

}   //每次上传成功一个文件后都会调用
函数进行接收的,所有自定义返回的参数都放在了msg中,如下所示可以取出name和uuid的值。
var msg = eval("(" + file.msg + ")");
console.info(msg.map.name+"    "+msg.map.uuid);

这里还要说一点,先前我是将文件直接缓存到当前年月日的目录下,这样可以降低服务器在移动文件损耗的性能,但是后来发现,如果用户上传的文件过大,跨过了晚上12点,因为是分段上传的,12点后上传的文件会放置到新的年月日文件夹中,那么则会出现12点后的文件衔接不上12点之前上传的部分文件了, 这样会导致失败,
于是后来牺牲了性能,将所有上传的文件先都缓存在一个固定目录下,然后上传完毕后移动到当前的年月日文件夹下。不一定是好的办法,暂时这样用了。

为了让大家更好的了解这个上传问题,这里贴出了我的代码地址:http://download.csdn.net/detail/qq_27063119/9630240  (6个金币下载,大家支持一下好吧,打这么多字不容易啊,实在没有金币就  至我邮件  nuohy@qq.com(不一定能够及时回复,请谅解!))

到这里基本就讲完了,谢谢大家!!!


2
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:20523次
    • 积分:595
    • 等级:
    • 排名:千里之外
    • 原创:39篇
    • 转载:3篇
    • 译文:0篇
    • 评论:19条
    最新评论