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 ?>
* 博客园: http://www.cnblogs.com/lihaiyan/
* 邮箱:1063385677@qq.com
* QQ: 1063385677
* Copyright ©2014 Lover雪儿
********************************************
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。