zoukankan      html  css  js  c++  java
  • Ajax实现大文件切割上传

    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 ?>

  • 相关阅读:
    java架构之路-(nginx使用详解)nginx的反向代理和优化配置
    java架构之路-(nginx使用详解)nginx的安装和基本配置
    java架构之路-(mysql底层原理)Mysql之让我们再深撸一次mysql
    java架构之路(mysql底层原理)Mysql之Explain使用详解
    java架构之路-(mysql底层原理)Mysql索引和查询引擎
    java架构之路(多线程)JMM和volatile关键字
    算法初步---基本的数据结构(java为例)
    python基础之Matplotlib库的使用一(平面图)
    使用NumPy、Numba的简单使用(二)
    使用NumPy、Numba的简单使用(一)
  • 原文地址:https://www.cnblogs.com/lihaiyan/p/4278853.html
Copyright © 2011-2022 走看看