title: slice large file into chunks and upload using ajax and html5 FileReader
body: <p>What I want to implement is:</p>
  
  <p>In the front end, I use the html5 file api to read the file, and then upload the file's content to the php backend using ajax, and it's ok if the filesize is small. However,if the file is big enough, it causes chrome to crash. So I split the large file into chunks using file.slice, when all chunks are uploaded to the php, merge the chunks into a single complete one.</p>
  
  <p>the code is as follows:</p>
  
  <p>the front end:</p>
  
  <pre><code>&lt;style&gt;
  #container {
       min-width:300px;
       min-height:200px;
       border:3px dashed #000;
  }
  &lt;/style&gt;
  &lt;div id='container'&gt;
  
  &lt;/div&gt;
  &lt;script&gt;
  function addDNDListener(obj){
      obj.addEventListener('dragover',function(e){
              e.preventDefault();
              e.stopPropagation();
      },false);
      obj.addEventListener('dragenter',function(e){
              e.preventDefault();
              e.stopPropagation();
      },false);
      obj.addEventListener('drop',function(e){
              e.preventDefault();
              e.stopPropagation();
              var ul = document.createElement("ul");
              var filelist = e.dataTransfer.files;
              for(var i=0;i&lt;filelist.length;i++){
                      var file = filelist[i];
                      var li = document.createElement('li');
                      li.innerHTML = '&lt;label id="'+file.name+'"&gt;'+file.name+':&lt;/label&gt;  &lt;progress value="0" max="100"&gt;&lt;/progress&gt;';
                      ul.appendChild(li);
              }
              document.getElementById('container').appendChild(ul);
              for(var i=0;i&lt;filelist.length;i++){
                      var file = filelist[i];
                      uploadFile(file);
              }
      },false);
  }
  
  function uploadFile(file){
      var loaded = 0;
      var step = 1024*1024;
      var total = file.size;
      var start = 0;
      var progress = document.getElementById(file.name).nextSibling;
  
      var reader = new FileReader();
  
      reader.onprogress = function(e){
              loaded += e.loaded;
              progress.value = (loaded/total) * 100;
      };
  
      reader.onload = function(e){
              var xhr = new XMLHttpRequest();
              var upload = xhr.upload;
              upload.addEventListener('load',function(){
                      if(loaded &lt;= total){
                              blob = file.slice(loaded,loaded+step+1);
                              reader.readAsBinaryString(blob);
                      }else{
                              loaded = total;
                      }
              },false);
              xhr.open("POST", "upload.php?fileName="+file.name+"&amp;nocache="+new Date().getTime());
              xhr.overrideMimeType("application/octet-stream");
              xhr.sendAsBinary(e.target.result);
      };
      var blob = file.slice(start,start+step+1);
      reader.readAsBinaryString(blob);
  }
  
  window.onload = function(){
  
      addDNDListener(document.getElementById('container'));
      if(!XMLHttpRequest.prototype.sendAsBinary){ 
                XMLHttpRequest.prototype.sendAsBinary = function(datastr) {  
                          function byteValue(x) {  
                              return x.charCodeAt(0) &amp; 0xff;  
                          }  
                          var ords = Array.prototype.map.call(datastr, byteValue);  
                          var ui8a = new Uint8Array(ords);  
                          try{
                              this.send(ui8a);
                          }catch(e){
                              this.send(ui8a.buffer);
                          }  
                };  
      }
  };
  &lt;/script&gt;
  </code></pre>
  
  <p>the php code:</p>
  
  <pre><code>&lt;?php
       $filename = "upload/".$_GET['fileName'];
       //$filename = "upload/".$_GET['fileName']."_".$_GET['nocache'];
       $xmlstr = $GLOBALS['HTTP_RAW_POST_DATA'];
       if(empty($xmlstr)){
               $xmlstr = file_get_contents('php://input');
       }
       $is_ok = false;
       while(!$is_ok){
              $file = fopen($filename,"ab");
  
              if(flock($file,LOCK_EX)){
                      fwrite($file,$xmlstr);
                      flock($file,LOCK_UN);
                      fclose($file);
                      $is_ok = true;
              }else{
                      fclose($file);
                      sleep(3);
              }
      }
  </code></pre>
  
  <p>The problem is, after the chunks of the file all being uploaded to the server and merged into a new one, the total file size is smaller than the original, and the merged one is broken. Where is the problem and how to fix it?</p>