在PHP中合并文件块

时间:2016-03-16 19:53:07

标签: javascript file-upload chunks

出于教育目的,我想创建文件块上传。当你们上传所有的块时,你们怎么知道?

我尝试从temp移动块并重命名它们以使它们的顺序正确,然后将最后一个块合并在一起。然而,最后一件作品不是收到的最后一件,我猜。所以块上的fopen()失败了,因为它们尚未创建,我得到的最终文件的大小与上一个块的大小完全相同。

我相信我可以使用.onload xhr上的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 < size) { chunkUpload(file.slice(start, end)); start = end; end = start + BYTES_PER_CHUNK; num++; } } 事件逐个发送数据块,这样我就不必将它们从PHP临时移动,但我想知道如果有不同的解决方案。

取悦你的一些基本代码:

$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 <= $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);
  }
}

和PHP:

aSelectedDataSet.forEach(function(currentObject,index){

     for (var childObject in currentObject) {
         if (! currentObject.hasOwnProperty(childObject))
             continue;

          var objectToClone = oData[childObject]['results'][index];

          if(objectToClone)
              $.extend(true,currentObject[childObject],objectToClone);
     }
  });

1 个答案:

答案 0 :(得分:4)

对不起我之前的评论,我误解了一个问题。这种静谧很有趣,也很有趣。

您正在寻找的表达方式是:

$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);

// count ammount of uploaded chunks
$chunksUploaded = 0;
for ( $i = 1, i <= $num; $i++ ) {
    if ( file_exists( $target_file.$i ) ) {
         ++$chunksUploaded;
    }
}

// and THAT's what you were asking for
// when this triggers - that means your chunks are uploaded
if ($chunksUploaded === $num_chunks) {

    /* here you can reassemble chunks together */
    for ($i = 1; $i <= $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);
    }
}

必须提到这一点:

我的版本的脆弱点 - 是你期待的文件

  • &#39; TMP-1&#39;,

  • &#39; TMP-2&#39;,

  • &#39; TMP-3&#39;

但是,让我们假设发送&#t; tmp-2&#39;我们被打断了 - tmp-2污染了tmp文件夹,它将干扰未来使用相同文件名的上传 - 这将是一个沉睡的炸弹。

要反击 - 你必须找到一种方法将tmp改为更原始的东西。

  • &#39; TMP-ABCew-1&#39;,

  • &#39; TMP-ABCew-2&#39;,

  • &#39; TMP-ABCew-3&#39;

有点好 - 在哪里&#39; ABCew&#39;可以被称为&#39; chunksSessionId&#39; - 您在发送POST时提供它,您随机进行。然而,碰撞是可能的 - 随机名称的空间耗尽。您可以为方程式添加时间 - 例如 - 您可以看到

  • &#39; TMP-ABCew-2016-03-17-00-11-22--1&#39;,

  • &#39; TMP-ABCew-2016-03-17-00-11-22--2&#39;,

  • &#39; TMP-ABCew-2016-03-17-00-11-22--3&#39;

更具抗冲突性,但很难实现 - 这里有一整套蠕虫 - 客户端日期和时间由客户端控制,可能会被欺骗 - 这些数据不可靠。

因此,使tmp-name独特是一项复杂的任务。设计一个让它变得可靠的系统 - 这是一个有趣的问题^ ^你可以使用它。

相关问题