简体   繁体   English

在PHP中将文件块粘合在一起

[英]Glue chunks of files together in PHP

I've written a File API uploader, which essentially does the following: 我已经编写了File API上载器,它实际上执行以下操作:

  1. User selects files to upload 用户选择要上传的文件
  2. The files are sliced into 20 kb chunks 将文件切成20 kb的块
  3. The chunks are sent asynchronous to a php script 块被异步发送到php脚本
  4. PHP waits until all chunks are uploaded, and then glues all the temporary files together PHP等待直到所有块都上传完毕,然后将所有临时文件粘合在一起
  5. The file - glued together - is saved 粘贴在一起的文件已保存

However, PHP doesn't glue them together very well. 但是,PHP不能很好地将它们粘合在一起。 Sometimes, the file is glued together well, but most of the times (especially on files with a lot of chunks) the file's are glued together wrong. 有时,文件被很好地粘合在一起,但是大多数情况下(尤其是在有很多块的文件上),文件被错误地粘合在一起。

The js code: (works only in Firefox 4 beta): js代码:(仅在Firefox 4 beta中有效):

 sendChunk: function(file, start, length) {
    var raw  = file.raw;
    var name  = file.name;
    var total  = file.size;

    var url = 'upload.php?name=' + encodeURIComponent(name) + '&total=' + total + '&start=' + start + '&length=' + length;
    var slice = raw.slice(start, length);
    var reader  = new FileReader();

    reader.readAsBinaryString(slice);
    reader.onload = function(e) {
        if(e.target.readyState === FileReader.DONE) {
            var xhr = new XMLHttpRequest();
            xhr.open("POST", url);
            xhr.overrideMimeType('text/plain; charset=x-user-defined-binary');
            xhr.sendAsBinary(e.target.result);
        }
    };
};

The PHP code: PHP代码:

<?php
$filename = $_GET['name'];
$total = $_GET['total'];
$start = $_GET['start'];
$length = $_GET['length'];

$uploaded = $start + $length;
$percentage = round($uploaded / ($total / 100));
$remaining = $total - $uploaded;

$fd = fopen("php://input", "r");
while($data = fread( $fd, 10000000)) file_put_contents("./tmp/$filename.$start", $data, FILE_APPEND);

if($remaining <= 0) {
    $handle  = opendir('tmp/');
    $data   = '';
    $collection = array();

    while(($file = readdir($handle)) !== false) {
        $arr  = explode('.', $file);
        $name  = '';
        $start  = $arr[count($arr) - 1];

        for($i = 0; $i < (count($arr) - 1); $i++) {
            if($name == '') $name .= $arr[$i];
            else $name .= '.' . $arr[$i];
        }

        if($name == $filename) {
            $collection[$start] = file_get_contents('./tmp/' . $file);
        }

        @unlink('./tmp/' . $file);
    }

    ksort($collection);

    foreach($collection as $key => $bin) {
        echo "(Added) $key: (binary data)\n";
        $data .= $bin;
    }

    if($data !== '') {
        file_put_contents('./uploads/' . $filename, $data);
    }

    closedir($handle);
} else {
    echo "Uploaded: $uploaded / $total ($percentage%)\n";
    echo "Remaining: " . $remaining . " (". (100 - $percentage) ."%)\n";
}
?>

Anybody has any idea? 有人知道吗? My guess is that the FileReader works asynchronous, and it somehow sends the wrong chunk with the wrong start & length parameters in the sendChunk method. 我的猜测是FileReader异步工作,并且它在sendChunk方法中以某种方式发送了带有错误的startlength参数的错误块。

I am not familiar with the way you are sending the data to the server, but I my first guess would be to change 我不熟悉将数据发送到服务器的方式,但是我的第一个猜测是要更改

$fd = fopen("php://input", "r");

to

$fd = fopen("php://input", "rb");

so the stream-reader is binary-safe. 因此,流读取器是二进制安全的。

Edit: 编辑:

Since I am not familiar with the php://input stream and I don't know exaclty what data it includes and in what format, I recommend using POST data instead both in client and serverside. 由于我不熟悉php:// input流,也不知道它包含的数据以及格式是什么,我建议在客户端和服务器端都使用POST数据。

So I would change JS like this: 因此,我将像这样更改JS:

            var xhr = new XMLHttpRequest();
            xhr.open("POST", url);
            xhr.overrideMimeType("Content-type", "application/x-www-form-urlencoded");
            xhr.send('data='+encodeURIComponent(e.target.result));

and the PHP like this: 和PHP像这样:

file_put_contents("./tmp/$filename.$start", $_POST['data']);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM