Question

jQuery-File-Upload

Upload script:

$('#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)+'%'});
    }
});

In my api/combox_upload.php script I echo json_encode($_FILES) and half the time it comes back blank (I'm watching the XHR request responses in Chrome developer toolbar).

Why is that? How do I fix it so it always submits the file?

Edit: It seems to happen more frequently with larger files.

Could it be an issue with PHP not handling multipart data correctly? I noticed the XHR request comes in immediately, as soon as the file upload begins, but PHP obviously hasn't gotten the whole file yet... so what does it do? Does it block when I try to access the $_FILES object or does it just give me an empty array? Do I have to something special?

Was it helpful?

Solution

Through trial and error I discovered that this problem only occurs with files larger than about 23 MiB. I'm not sure if that's a universal constant or specific to how my server is configured.

Nevertheless, I figured out how to get around this limitation. You need to set singleFileUploads to true and multipart to false, e.g.

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

And then in your php script you can read in the data like this:

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

$file_data = '';

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

fclose($handle);

The $_FILES array will still be empty, so you can't get the filename out of there, but it seems to be set in the Content-Disposition header. I wrote a regex to pull it out:

$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';
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top