2016-03-16 3 views
3

В образовательных целях я хотел создать загрузку файлов. Как вы, ребята, знаете, когда загружаются все куски?Слияние фрагментов файлов в PHP

Я попытался переместить куски с temp и переименовать их так, чтобы они были в правильном порядке, а затем с последним куском объединить их вместе. Как бы то ни было, последний фрагмент не является последним. Таким образом, fopen() на кусках терпит неудачу, так как они еще не созданы, и я получаю окончательный файл размером, размером с последний кусок.

Я считаю, что я мог бы отправлять куски один за другим с помощью .onload событий на xhr, поэтому мне не пришлось бы даже перемещать их из PHP-темпа, но мне интересно, есть ли разные решения.

Некоторые базовый код, чтобы порадовать вас:

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

ответ

2

Извините за мои предыдущие комментарии, я понял вопрос. Это интересное и интересное занятие.

Выражение вы ищете это:

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

И это должно быть упомянуто:

Точка хрупкости моей версии - это когда вы ожидаете файлы

  • ' tmp-1 ',

  • ' tmp-2 ',

  • 'ТМП-3'

, но давайте предположим, что после отправки 'ТМП-2' мы были прерваны - что ТМП-2 загрязняет папку TMP, и это будет мешать с будущими загрузки с тем же filename - это будет спящая бомба.

Чтобы противостоять этому - вы должны найти способ изменить tmp на нечто более оригинальное.

  • 'ТМП-ABCew-1',

  • 'ТМП-ABCew-2',

  • 'TMP-ABCew-3'

немного лучше - где «ABCew» можно назвать «chunksSessionId» - вы предоставляете его при отправке POST, вы делаете это случайным образом. Тем не менее, возможны столкновения - так как пространство случайных имен истощается.Вы можете добавить время уравнения - например, - вы можете увидеть, что

  • 'ТМП-ABCew-2016-03-17-00-11-22--1',

  • «tmp- ABCew-2016-03-17-00-11-22--2' ,

  • 'ТМП-ABCew-2016-03-17-00-11-22--3'

Это намного более устойчиво к столкновению, но его сложно реализовать - здесь может быть целая червь червей - дата и время клиента - это contro клики и могут быть подделаны - эти данные ненадежны.

Так что создание уникального имени tmp-name - сложная задача. Проектирование системы, которая делает ее надежной - интересная проблема^^ Вы можете играть с этим.

+0

Спасибо, не знаю, почему я не думал просто проверять, существуют ли файлы. О именах temp - да, это то, что я тоже принимаю во внимание. Ну, проблема может возникнуть только в том случае, если пользователь попытается загрузить два или более файлов с тем же именем одновременно, потому что я использую имя реального файла в качестве идентификатора, но я думаю, что я буду использовать какую-то временную метку, чтобы идентифицировать их жестко , Другой способ - создать временную папку для каждой части куска и использовать для нее какое-то случайное имя. Спасибо за ваш замечательный ответ еще раз! – Innan

Смежные вопросы