Lover雪儿
想念时,就看看天空,无论距离有多远,我们总在同一片天空下!

Ajax大文件切割上传

2015-02-07

 

前面我们已经实现了Ajax的文件上传,不过会受限于服务器的允许的大小,

如果服务器并非自己的,我们就要使用Ajax大文件切割来实现上传。

 

首先解决Ajax跨域上传问题:

在HTML5中,ajax的跨域有了新的规则-----能否跨域取决于对应的应答。

对方服务器如果愿意接受远程过来的ajax,或某几个域名过来的ajax请求,可以在头信息header中,加入Access-Control-Allow-Origin *

在PHP中加入此信息,就可以实现跨域请求。

 

一、简陋的文件时上传思路

截取用到的API

     file->继承自->Blob

     Blob有slice方法,可以截取二进制对象的一部分

     思路:截取10M,上传

     判断文件有没有截取完毕

     while 还有数据{

         截取

        上传

     }

html文件代码:

 

 1 <html>
 2     <head>
 3     <title>FormData</title>    
 4     <script type="text/javascript">
 5 */
 6     /*用到的API
 7      file->继承自->Blob
 8      Blob有slice方法,可以截取二进制对象的一部分
 9      思路:截取10M,上传
10      判断文件有没有截取完毕
11      while 还有数据{
12          截取
13         上传
14      }
15          
16      */
17 function selectfile(){
18     const LENGTH = 10 * 1024 * 1024; //每次截取的长度
19     var sta = 0;        //从零处开始截取
20     var end = sta +LENGTH; 
21     var blob = null;
22     var fd = null;
23     var xhr = null;
24     var percent = 0;
25 
26     /* blob对象 */
27     var mov = document.getElementsByTagName('input')[0].files[0];
28     var totalsize = mov.size;
29 
30     
31     while(sta < totalsize){
32         blob = mov.slice(sta,end);
33         fd = new FormData(); //定义一个FormData数组    
34         fd.append('part',blob);//格式化
35         
36         xhr = new XMLHttpRequest();
37       //post发送
38       xhr.open('POST','HTML5upJinDuTiao_DaWenJianShangchuan.php',false);    
39 
40         xhr.onreadystatechange = function(){
41             if(this.readyState == 4){
42                 document.getElementById('debug').innerHTML = this.responseText;
43             }
44         }    
45         console.log(blob);            
46 
47         xhr.send(fd);
48         sta = end;
49         end +=LENGTH;    
50     }
51 }
52 
53     </script>
54 
55 <style type='text/css'>
56     img{ width:500px; }
57     #progress{width:500px; height:15px; border:1px solid green;}
58     #bar{width:0%; height:100%; background:green;}
59 </style>
60 
61 
62     </head>
63     <body>
64         <h1>ajax大文件切割上传</h1>
65         <input type="file" name="pic" onchange="selectfile();" />
66         <hr/>
67         <div id="progress">
68             <div id="bar"></div>
69         </div>
70         <div id="debug2"></div>
71         <hr/>
72         <div id="debug"></div>
73         
74 
75     </body>
76 </html>
77                 

 

php文件代码:

 

 1 <?php
 2 
 3 /*接收文件并合并*/
 4 
 5 print_r($_FILES);
 6 
 7 if(!file_exists('./upload/up.mp4')){
 8     move_uploaded_file($_FILES['part']['tmp_name'],'./upload/up.mp4');
 9 }else{
10     file_put_contents('./upload/up.mp4',file_get_contents('./upload/up.mp4').file_get_contents($_FILES['part']['tmp_name']));
11 }
12 
13 echo 'ok';
14 
15 ?>

 

 

这个是一个简陋的大文件切割上传程序,如果想看进度,或者查看其是否再上传,我们必须按下F12,在控制台中看,文件没切割一次,相应的信息就会在控制台中显示一行。

 

 

二、改进(增加上传进度条)

由于浏览器对页面渲染的优化,如果要增加上传进度条显示的话,经过浏览器的渲染优化,我们的进度条在上传是不会增加,而是在上传完毕后,直接从0增加对100,这个是无法忍受的。

原因是:浏览器渲染的优化,reflow具体可以网上找相应的详细资料。

为了增加进度条效果,我们可以使用window的定时器,

clock = window.setInterval(selectfile,1000);

让它每秒钟刷新一下页面,计算当前上传进度,显示出来。

 

html文件代码:

 

 1 <html>
 2     <head>
 3     <title>FormData</title>    
 4     <script type="text/javascript">
 5 
 6     /*用到的API
 7      file->继承自->Blob
 8      Blob有slice方法,可以截取二进制对象的一部分
 9      思路:截取10M,上传
10      判断文件有没有截取完毕
11      利用定时器不断的调用
12      */
13 xhr = new XMLHttpRequest();
14 var clock = null;
15 
16 //file选择,触发定时器函数
17 function selectfile_fire(){
18     clock = window.setInterval(selectfile,1000);
19     //定时1s
20 }
21 
22 //闭包函数
23 var selectfile = (function(){
24      const LENGTH = 10*1024*1024;//每次截取的长度
25     var sta = 0;                //从零处开始截取
26     var end = sta +LENGTH;
27     var flag = false;    //表示上一块是否发送完毕
28     var blob = null;
29     var fd = null;
30     var percent = 0;
31 
32         //匿名函数
33     return(function (){
34         alert("aa");
35         if(flag == true){    //是否正在上传
36             return;
37         }
38         flag = true;
39         var mov = document.getElementsByTagName('input')[0].files[0];/* blob对象 */
40         
41         fd = new FormData();
42         blob = mov.slice(sta,end);
43         fd.append('part',blob);
44         up(fd);
45 
46         //如果sta > mov.size 就结束
47         if(sta >= mov.size){
48             clearInterval(clock);    //清除定时
49             return ;
50         }
51         sta = end;
52         end = sta + LENGTH;
53         flag = false;    //上传完毕
54         
55         percent = 100 * end /mov.size ;
56         percent = percent >= 100 ? 100 : percent;
57         document.getElementById('bar').style.width = percent + "%";
58         document.getElementById('bar').innerHTML =  parseInt(percent) + "%"  ;
59 
60     });
61 })();
62 
63 /*利用定时器不断调用*/
64 function  up(fd){
65     xhr.open('POST','HTML5upJinDuTiao_DaWenJianShangchuan.php',false);    //post发送
66     xhr.send(fd);
67 }
68 
69 
70     </script>
71 
72 <style type='text/css'>
73     img{ width:500px; }
74     #progress{width:500px; height:15px; border:1px solid green;}
75     #bar{width:0%; height:100%; background:green;}
76 </style>
77 
78 
79     </head>
80     <body>
81         <h1>ajax大文件切割上传</h1>
82         <input type="file" name="pic" onchange="selectfile_fire();" />
83         <hr/>
84         <div id="progress">
85             <div id="bar"></div>
86         </div>
87         <div id="debug2"></div>
88         <hr/>
89         <div id="debug"></div>
90         
91 
92     </body>
93 </html>

 

 

 

php文件代码:

 

 1 <?php
 2 
 3 /*接收文件并合并*/
 4 
 5 print_r($_FILES);
 6 
 7 if(!file_exists('./upload/up.mp4')){
 8     move_uploaded_file($_FILES['part']['tmp_name'],'./upload/up.mp4');
 9 }else{
10     file_put_contents('./upload/up.mp4',file_get_contents('./upload/up.mp4').file_get_contents($_FILES['part']['tmp_name']));
11 }
12 
13 echo 'ok';
14 
15 ?>

 

 

posted on 2015-02-07 15:19  Lover雪儿  阅读(1126)  评论(0编辑  收藏  举报