【问题标题】:Glue chunks of files together in PHP在 PHP 中将文件块粘合在一起
【发布时间】:2011-01-21 18:26:22
【问题描述】:

我编写了一个 File API 上传器,它主要执行以下操作:

  1. 用户选择要上传的文件
  2. 文件被分割成 20 kb 的块
  3. 块被异步发送到 php 脚本
  4. PHP 等待所有块上传完毕,然后将所有临时文件粘合在一起
  5. 文件 - 粘合在一起 - 已保存

但是,PHP 不能很好地将它们粘合在一起。有时,文件很好地粘合在一起,但大多数时候(尤其是在具有很多块的文件上)文件的粘合在一起是错误的。

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

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";
}
?>

有人知道吗?我的猜测是 FileReader 是异步工作的,它以某种方式在 sendChunk 方法中使用错误的 startlength 参数发送了错误的块。

【问题讨论】:

  • 您应该格式化您的代码以提高可读性! ;-)
  • 也许使用 $_FILES 而不是从标准输入读取会更容易。
  • 好吧,那行不通,因为我不将它作为 multipart/form-data 发送
  • 这是一个非常好的主意(分块发送)。也许您可以将 ajax 请求排队,以便一次只发送一个?另外,您是否检查数据确实是服务器端的图像,如果是,如何检查?

标签: php javascript upload


【解决方案1】:

我不熟悉您将数据发送到服务器的方式,但我的第一个猜测是改变

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

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

所以流阅读器是二进制安全的。

编辑:

由于我不熟悉 php://input 流,也不知道它包含什么数据以及采用什么格式,我建议在客户端和服务器端都使用 POST 数据。

所以我会这样改变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));

还有这样的 PHP:

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

【讨论】:

  • 嗯,它做了一些事情......现在看看输出:fabdrol.com.s3.amazonaws.com/1415_IMG_8799.jpg
  • 是否可以使用diff 之类的工具来查看您的数据在哪里被更改?
  • 如果您还没有解决方案,请添加新想法
猜你喜欢
  • 2019-01-08
  • 1970-01-01
  • 2010-12-26
  • 2016-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多