title: Merging file chunks in PHP
body: <p>For the educational purposes, I wanted to create file chunks upload. How do you guys know when all of the chunks are uploaded?</p>
  
  <p>I tried to move chunks from <code>temp</code> and renaming them so they are in correct order, and then with the last chunk merge them together. However the last piece sent is not the last piece received, I guess. So <code>fopen()</code> on chunks fails since they're not created yet, and I get final file with the size exactly the size of the last chunk.</p>
  
  <p>I believe I could send chunks one by one using <code>.onload</code> event on <code>xhr</code>, that way I wouldn't have to even move them from PHP temp, but I'm wondering if there are different solutions.</p>
  
  <p>Some basic code to please you:</p>
  
  <pre><code>function upload(file) {
    var BYTES_PER_CHUNK = parseInt(2097152, 10),
    size = file.size,
    NUM_CHUNKS = Math.max(Math.ceil(SIZE / BYTES_PER_CHUNK), 1),
    start = 0, end = BYTES_PER_CHUNK, num = 1;
  
    var chunkUpload = function(blob) {
      var fd = new FormData();
      var xhr = new XMLHttpRequest();
  
      fd.append('upload', blob, file.name);
      fd.append('num', num);
      fd.append('num_chunks', NUM_CHUNKS);
      xhr.open('POST', '/somedir/upload.php', true);
      xhr.send(fd);
    }
  
    while (start &lt; size) {
      chunkUpload(file.slice(start, end));
      start = end;
      end = start + BYTES_PER_CHUNK;
      num++;
    }
  }
  </code></pre>
  
  <p>And PHP:</p>
  
  <pre><code>$target_path = ROOT.'/upload/';
  
  $tmp_name = $_FILES['upload']['tmp_name'];
  $filename = $_FILES['upload']['name'];
  $target_file = $target_path.$filename;
  $num = $_POST['num'];
  $num_chunks = $_POST['num_chunks'];
  
  move_uploaded_file($tmp_name, $target_file.$num);
  
  if ($num === $num_chunks) {
    for ($i = 1; $i &lt;= $num_chunks; $i++) {
  
      $file = fopen($target_file.$i, 'rb');
      $buff = fread($file, 2097152);
      fclose($file);
  
      $final = fopen($target_file, 'ab');
      $write = fwrite($final, $buff);
      fclose($final);
  
      unlink($target_file.$i);
    }
  }
  </code></pre>