简体   繁体   中英

php://input is empty for requests less than 10MB

Problem:

Raw POST requests lower than 10MB don't reach php://input buffer. I have no problem with requests over 10MB.
Anyone having a clue?

System:
OS: Ubuntu 16.04
Software: Apache with Nginx & PHP 7

Story:
I have used blueimp jQuery fileupload on one of my website. The files that I upload are large, over 1GB. The upload script uploads in chunks of 10MB, but the last chunk never gets uploaded. When I lowered the chunk size to 5MB, not even the first chunk gets uploaded.
I have watched the upload in Firefox developer tools, the request is made and it's valid.

var abort_transfer = false;
$('#fileupload').fileupload({
    url: 'my_url',
    dataType: 'json',
    maxChunkSize: 1000000,
    add: function(e, data) {
        data.submit();
    },
    send: function(e, data) {
        $('button[type="submit"]').prop("disabled", true);
    },
    done: function(e, data) {
        console.log('done', e, data);
        $('button[type="submit"]').prop("disabled", false);
    },
    fail: function(e, data) {
        console.log('fail', e, data);
    },
    chunksend: function(e, data) {
        if (abort_transfer) return false;
    },
    chunkdone: function(e, data) {
        if (data['jqXHR']['responseJSON']['status'] == 'nok') {
            abort_transfer = true;
            console.log('chunkdone', data['jqXHR']['responseJSON']);
        }
    },
    progressall: function(e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        $('#progress').css('width', progress + '%').text(progress + '%');
    },
    formData: function(form) {
        return [
            {name: 'action', value: 'upload-large-file'}
        ];
    }
})
.prop('disabled', !$.support.fileInput);

I found the problem.

My PHP settings were:
upload_max_filesize 2M
post_max_size 8M

TL & DR

  • I didn't had code to handle the last chunk in $_POST
  • I lowered the chunk size to either upload_max_filesize or either post_max_size , whichever is lower, minus the boundaries

Something peculiar

The blueimp jQuery fileupload sends the chunks in php//:input buffer, but the last chunk. The last chunk is sent in $_POST .

What I have changed

I added code to handle the last chunk in $_POST:

Because the $_POST chunk was bigger then the upload_max_filesize, it didn't arrived (gave error 1 in $_FILES['file']['error'] ).

I lowered the chunk size:

$post_max_size = (int)ini_get('post_max_size') * (substr(ini_get('post_max_size'), -1) == 'M' ? pow(1024, 2) : pow(1024, 3));
$upload_max_filesize = (int)ini_get('upload_max_filesize') * (substr(ini_get('upload_max_filesize'), -1) == 'M' ? pow(1024, 2) : pow(1024, 3));
$chunk_size = min($post_max_size, $upload_max_filesize) - (10 * 1024);

Also, note that a chunk is higher then the set value because it contain the boundaries and post data. So, the $chunk_size was lowered 10KB to be sure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM