2012-03-13 4 views
4

ファイルアップロード機能があり、html5のスライスapiを使用して、各ファイルを1MBのチャンクにスライスしますが、最終的な結果でファイルが破損します。時には、最終結果が元のファイルよりも小さく、時には正しいサイズであっても、私はまだそれを開くことができません。誰もが考えている?またはソリューションですか? 私は私のPHPコードをサーバー上で一緒にファイルを入れたときに、私は何か間違ったことをしたと思う。これはHTML5スライス、結果ファイルが壊れています

 var uploaders = []; 
     var i = 0; 
     $(document).ready(function() { 
      var progress = document.querySelector('progress'); 
      var bars = document.querySelector('#bars'); 
     });   

     //function for after the button is clicked, slice the file 
     //and call upload function 
     function sendRequest() {  
      //clean the screen 
      bars.innerHTML = ''; 
      var blob = document.getElementById('fileToUpload').files[0]; 
      var originalFileName = blob.name; 
      const BYTES_PER_CHUNK = 1 * 1024 * 1024; // 10MB chunk sizes. 
      const SIZE = blob.size; 

      var start = 0; 
      var end = BYTES_PER_CHUNK; 

      while(start < SIZE) {      
       if (blob.webkitSlice) { 
        var chunk = blob.webkitSlice(start, end); 
       } else if (blob.mozSlice) { 
        var chunk = blob.mozSlice(start, end); 
       }  

       uploadFile(chunk, originalFileName); 
       start = end; 
       end = start + BYTES_PER_CHUNK; 
      } 
     } 

     function uploadFile(blobFile, fileName) { 
      var progress = document.createElement('progress'); 
      progress.min = 0; 
      progress.max = 100; 
      progress.value = 0; 
      bars.appendChild(progress); 

      var fd = new FormData(); 
      fd.append("fileToUpload", blobFile); 

      var xhr = new XMLHttpRequest();     
      xhr.open("POST", "upload.php"+"?"+"file="+fileName + i, true); 
      i++; 

      xhr.onload = function(e) { 
       //make sure if finish progress bar at 100% 
       progress.value = 100; 

       //counter if everything is done using stack 
       uploaders.pop(); 

       if (!uploaders.length) { 
        bars.appendChild(document.createElement('br')); 
        bars.appendChild(document.createTextNode('DONE :)')); 
       }     
      }; 

      // Listen to the upload progress for each upload. 
      xhr.upload.onprogress = function(e) {; 
       if (e.lengthComputable) { 
        progress.value = (e.loaded/e.total) * 100; 
       } 
      };     

      uploaders.push(xhr); 
      xhr.send(fd); 
     }  

をスライスするための部分であり、これはバイナリチャンク

<?php 

$target_path = "uploads/"; 
$tmp_name = $_FILES['fileToUpload']['tmp_name']; 
$size = $_FILES['fileToUpload']['size']; 
$name = $_FILES['fileToUpload']['name']; 

$originalName = $_GET['file1']; 

print_r("*******************************************\n"); 

print_r($originalName); 
print_r("\n"); 

print_r($_FILES); 
print_r("\n"); 

print_r("*******************************************\n"); 
$target_file = $target_path . basename($name); 

//Result File 
$complete = $originalName; 
$com = fopen("uploads/".$complete, "ab"); 
error_log($target_path); 

if ($com) { 
    // Read binary input stream and append it to temp file 
    $in = fopen($tmp_name, "rb"); 
    if ($in) { 
     while ($buff = fread($in, 1048576)) { 
      fwrite($com, $buff); 
     } 
    } 
    fclose($in); 
    fclose($com); 
} 


?> 

を受け入れるためのPHPファイルであります(私はそれを順序や何かに入れないのと同じように)、だれかがこのやベストプラクティスをやる方法を知っているのだろうか?ファイルをアップロードして組み合わせるのではなく、ファイルに実際に書き込む前に、まずメモリに保存しておいてください。

+0

あなたuploadprogressの機能を提供してください。変数bar(div?)はスクリプト内で定義されていません。また、uploaders変数の値を省略しています(配列なのですか?) – Martin

+0

@Martinコードを更新しました。これは、コード全体を表しています。ファイルのアップロードのための通常のhtmlタグを除いて – Harts

答えて

8

ファイルの複数のチャンクを一度にアップロードし、最後にマージします。

const BYTES_PER_CHUNK = 1024 * 1024; // 1MB chunk sizes. 
var slices; 
var slices2; 

function sendRequest() { 
    var xhr; 
    var blob = document.getElementById('fileToUpload').files[0]; 

    var start = 0; 
    var end; 
    var index = 0; 

    // calculate the number of slices we will need 
    slices = Math.ceil(blob.size/BYTES_PER_CHUNK); 
    slices2 = slices; 

    while(start < blob.size) { 
     end = start + BYTES_PER_CHUNK; 
     if(end > blob.size) { 
      end = blob.size; 
     } 

     uploadFile(blob, index, start, end); 

     start = end; 
     index++; 
    } 
} 

function uploadFile(blob, index, start, end) { 
    var xhr; 
    var end; 
    var fd; 
    var chunk; 
    var url; 

    xhr = new XMLHttpRequest(); 

    xhr.onreadystatechange = function() { 
     if(xhr.readyState == 4) { 
      if(xhr.responseText) { 
       alert(xhr.responseText); 
      } 

      slices--; 

      // if we have finished all slices 
      if(slices == 0) { 
       mergeFile(blob); 
      } 
     } 
    }; 

    if (blob.webkitSlice) { 
     chunk = blob.webkitSlice(start, end); 
    } else if (blob.mozSlice) { 
     chunk = blob.mozSlice(start, end); 
    } 

    fd = new FormData(); 
    fd.append("file", chunk); 
    fd.append("name", blob.name); 
    fd.append("index", index); 

    xhr.open("POST", "upload.php", true); 
    xhr.send(fd); 
} 

function mergeFile(blob) { 
    var xhr; 
    var fd; 

    xhr = new XMLHttpRequest(); 

    fd = new FormData(); 
    fd.append("name", blob.name); 
    fd.append("index", slices2); 

    xhr.open("POST", "merge.php", true); 
    xhr.send(fd); 
} 

はupload.php使って作品を収集します。

if(!isset($_REQUEST['name'])) throw new Exception('Name required'); 
if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error'); 

if(!isset($_REQUEST['index'])) throw new Exception('Index required'); 
if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error'); 

if(!isset($_FILES['file'])) throw new Exception('Upload required'); 
if($_FILES['file']['error'] != 0) throw new Exception('Upload error'); 

$target = "uploads/" . $_REQUEST['name'] . '-' . $_REQUEST['index']; 

move_uploaded_file($_FILES['file']['tmp_name'], $target); 

// Might execute too quickly. 
sleep(1); 

はmerge.phpを使って作品をマージ:

if(!isset($_REQUEST['name'])) throw new Exception('Name required'); 
if(!preg_match('/^[-a-z0-9_][-a-z0-9_.]*$/i', $_REQUEST['name'])) throw new Exception('Name error'); 

if(!isset($_REQUEST['index'])) throw new Exception('Index required'); 
if(!preg_match('/^[0-9]+$/', $_REQUEST['index'])) throw new Exception('Index error'); 

$target = "uploads/" . $_REQUEST['name']; 
$dst = fopen($target, 'wb'); 

for($i = 0; $i < $_REQUEST['index']; $i++) { 
    $slice = $target . '-' . $i; 
    $src = fopen($slice, 'rb'); 
    stream_copy_to_stream($src, $dst); 
    fclose($src); 
    unlink($slice); 
} 

fclose($dst); 
+0

「最初のチャンクをアップロードし、次にxhr.onreadystatechangeへの応答として2番目のチャンクをアップロードする機能を書き直しました」と、チャンクの目的を失うことはありません。あなたは1つずつアップロードします。より遅いアップロードを引き起こします。 – Harts

+0

同じファイルの複数の部分を一度にアップロードする予定の場合は、サーバがどの部分が同じ時刻に到着するか順不同で到着する可能性があることをサーバに伝える必要もあります。サーバーは、組み立てるまで各部分を保持する必要があります。これはかなり複雑です。 – Martin

+0

それは私が探している答えのタイプです。私は一度に同じファイルの複数の部分をアップロードする必要がありますか、または私のプロジェクトのために、さらに複雑なファイルを複数同時にアップロードする必要があります。私が探しているのは、断片を順番にどのように組み合わせるかです。それはサーバーのメモリに最初に何か.. – Harts

関連する問題