jQuery-File-Upload不一致地提供文件数据

时间:2012-12-29 00:58:15

标签: javascript jquery-file-upload

jQuery-File-Upload

上传脚本:

$('#fileupload').fileupload({
    url: 'api/combox_upload.php',
    type: 'POST',
    dataType: 'json',
    dropZone: $dropZone,
    singleFileUploads: true,
    done: function (e, data) {
        attachments = attachments.concat(data.result);
        refreshAttachments();
    },
    add: function(e, data) {
        var file = data.files[0];
        data.context =
            $('<li>',{'class':'file-upload-item'})
                .append($('<span>').text(file.name))
                .append(
                    $('<div>',{'class':'progressbar'})
                    .append($('<div>',{'class':'progress'}))
                ).appendTo($fileUploads);
        data.submit(); // start upload immediately
    },
    progress: function(e, data) {
        var progress = data.loaded / data.total;
        data.context.find('.progress').stop().animate({'width':(progress*100)+'%'},100,'linear');
        //data.context.find('.progress').css({'width':(progress*100)+'%'});
    }
});

在我的api/combox_upload.php脚本echo json_encode($_FILES)中,有一半时间空白(我在Chrome开发者工具栏中观看XHR请求响应)。

为什么?如何修复它以便始终提交文件?

编辑:对于较大的文件,似乎更频繁地发生。

PHP是否无法正确处理多部分数据?我注意到XHR请求立即进入,一旦文件上传开始,但PHP显然还没有得到整个文件......那么它做了什么?当我尝试访问$_FILES对象时它是阻塞还是仅仅给我一个空数组?我需要特别的东西吗?

1 个答案:

答案 0 :(得分:2)

通过反复试验,我发现只有大于23 MiB的文件才会出现此问题。我不确定这是一个通用常量还是特定于我的服务器配置方式。

然而,我想出了如何解决这个限制。您需要将singleFileUploads设置为true并将multipart设置为false,例如

$('#fileupload').fileupload({
    url: 'api/upload.php',
    type: 'POST',
    dataType: 'json',
    singleFileUploads: true,
    multipart: false,
    ...

然后在您的php脚本中,您可以读取数据:

$handle = fopen('php://input', 'r');

$file_data = '';

while(($buffer = fgets($handle, 4096)) !== false) {
    $file_data .= $buffer;
}

fclose($handle);

$_FILES数组仍然为空,因此您无法从中获取文件名,但它似乎在Content-Disposition标题中设置。我写了一个正则表达式来解决它:

$headers = getallheaders();
$filesize = strlen($file_data);
if(isset($headers['Content-Disposition']) && preg_match('`\bfilename="((?:\\.|[^"])*)"`',$headers['Content-Disposition'], $m)) {
    $filename = urldecode($m[1]);
} else {
    $filename = 'unknown';
}