Reputation: 282885
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?
Upvotes: 1
Views: 1316
Reputation: 282885
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';
}
Upvotes: 2