Javascript chunked文件上传到PHP Server

时间:2014-06-20 10:07:39

标签: javascript php ajax file-upload fileapi

所以我在javascript中有这个函数将文件的一部分发送到服务器:

function ajaxPartUpload(url, packageNo, file, attachmentId)
        {
            var packageMaxSize = 10240; //1048576; //10485760; //reduced for tests
            var packageCount =  Math.ceil(file.size / packageMaxSize);
            var start = packageNo * packageMaxSize;
            var stop = (packageNo+1) * packageMaxSize - 1; 
            if ((packageNo+1) === packageCount || packageCount === 0) {
                stop = file.size - 1;
            }
            var blob = file.slice(start, stop);
            var reader = new FileReader();

        reader.onloadend = function (evt) {
            if (evt.target.readyState === FileReader.DONE) {
                var data = {
                    blob: reader.result,
                    partNo: packageNo,
                    lastPartNo: packageCount,
                    fileName: file.name,
                    fileType: file.type,
                    fileSize: file.size,
                    attachmentId: attachmentId,
                    multipart: true
                };

                $.ajax({
                    url: url,
                    type: 'post',
                    dataType: 'json',
                    data: data,
                    success: function(response) {
                        if (response.continue === false) {

                            return true;
                        } else {
                            ajaxPartUpload(url, packageNo+1, file, response.attachmentId);
                        }

                    }
                });
            }
        };

        reader.readAsBinaryString(blob);
    }

它按预期工作,我发布了我正在发送的文件的二进制数据。 在指定的URL下我有基本的脚本:

$attachment = V()->Attachment->find($_POST['attachmentId']);
        $destination_path = $attachment->getPath();
    $filePointer = fopen($destination_path, 'a');
            $written = fwrite($filePointer, $_POST['blob']);
            if ($written == false )
            {
                throw new Exception('File data not written');
            }
            fclose($filePointer);

只要我有文本文件就可以,但是当我尝试发送二进制文件时,我正在恢复的文件大小大约50%,并且已损坏,如果我制作块大小并不重要大到足以将所有文件保存在一个http请求中。我做错了什么?

我已经在发送之前在javascript中丢弃了'blob'的长度并且在php中收集了blob的长度:我有2个完全不同的结果,一个块最大1 MB文件有'28KB'(来自ls -lash) :

javascript:25755

php:36495

发生什么事了?当我累了文本文件时,一切都还可以。

@EDIT: 解 在JS改变:

blob: reader.result,

blob: window.btoa(reader.result),

在PHP中

$written = fwrite($filePointer, $_POST['blob']);

$written = fwrite($filePointer, base64_decode($_POST['blob']));

解决了这个问题。

2 个答案:

答案 0 :(得分:1)

我在javascript中添加了atob来读取我的结果,然后在使用base64_decode读取之前解码数据。它解决了这个问题。

问题是PHP以其他方式解释这个二进制数据,也许是字符串,我真的不知道。无论如何,发送“比特”更大的编码数据可以节省很多麻烦。

答案 1 :(得分:0)

尝试使用'b'标志打开文件,因为它是PHP文档推荐的:

来自http://php.net/manual/en/function.fopen.php

  

为了便于携带,强烈建议您在使用fopen()打开文件时始终使用'b'标志。

就这样吧:

$filePointer = fopen($destination_path, 'ab');

如果问题仍然存在,那么可能是因为并发问题,所以你应该用一些锁来保护上面的调用,以确保没有不同的php进程同时写入该文件。

您可以使用flock(),查看如何在此flock tutorial中使用它。