22

I'm trying to upload "large" files to my application. Users must be able to upload video files smallest than 200MB but seem the server drops the connections after 4MB or 30 seconds and the upload fails.

I've already set all the parameters in my php.inifile as this:

max_input_time = 320
max_execution_time = 320
max_file_uploads = 20
memory_limit = 512M
post_max_size = 201M
upload_max_filesize = 200M

Everything is working when I upload a file of 2MB @ 1Mbps/s (I don't know if is a problem relating to filesize or transfer time)

Live php_info() file can be reached at php_info

Although here is DropZone.js conf:

$("#dZUpload").dropzone({
     url: "/ajax/admin/admin.acceptVideo.php",
     maxFilesize: 209715200,
     acceptedFiles: "video/*",
     addRemoveLinks: true,
     dataType: "HTML",
     data: { id: '' },
     success: function (file, response, data) {
         var imgName = response;
         file.previewElement.classList.add("dz-success");
         $('#form_video').val(imgName);
     },
     error: function (file, response) {
     file.previewElement.classList.add("dz-error");
     }
});
Dropzone.autoDiscover = false;
Dropzone.prototype.defaultOptions.dictRemoveFile = "Rimuovi file";
Dropzone.prototype.defaultOptions.dictCancelUpload = "Annulla";

And here is the PHP script that handles uploads:

<?php
require_once '../db.config.php';

header('Content-Type: text/plain; charset=utf-8');

ini_set('upload_max_filesize', '200M');
ini_set('post_max_size', '201M');
ini_set('max_input_time', 320);
ini_set('memory_limit', '256M'); 


try {
    if (
        !isset($_FILES['file']['error']) ||
        is_array($_FILES['file']['error'])
    ) {
        throw new RuntimeException('Invalid parameters.');
    }

    switch ($_FILES['file']['error']) {
    case UPLOAD_ERR_OK:
        break;
    case UPLOAD_ERR_NO_FILE:
        throw new RuntimeException('No file sent.');
        break;
    case UPLOAD_ERR_INI_SIZE:
        break;
    case UPLOAD_ERR_FORM_SIZE:
        throw new RuntimeException('Exceeded filesize limit.');
        break;
    default:
        throw new RuntimeException('Unknown errors.');
        break;
}

    // check filesize. 
    if ($_FILES['file']['size'] > 209715200) {
        throw new RuntimeException('Exceeded filesize limit.');
    }

    // Check MIME Type.
    $finfo = new finfo(FILEINFO_MIME_TYPE);
    if (false === $ext = array_search(
            $finfo->file($_FILES['file']['tmp_name']),
            array(
                'mp4' => 'video/mp4',
                'mov' => 'video/mov',
                'avi' => 'video/avi',
            ),
            true
        )) {
        throw new RuntimeException('Invalid file format.');
    }

    // name uniquely.
    $fileName = sha1_file($_FILES['file']['tmp_name']);
    if (!move_uploaded_file($_FILES['file']['tmp_name'], sprintf('/var/www/html/beta.vedocompro.it/web/webtemp/%s.%s', $fileName, $ext ))) {
        throw new RuntimeException('Failed to move uploaded file.');
    }

    try {

        $PDO = new PDO('mysql:host=' . $DB_HOST . ';dbname=' . $DB_NAME,$DB_USER,$DB_PASS);
        $insert = $PDO->prepare("INSERT INTO `videos` (`id`, `aid`, `accepted`, `uid`, `dir`) VALUES (NULL, '0', '0', '0', $fileName);");
        $insert->execute();

        echo $fileName;

    } catch(PDOException $exception) {
        echo $exception;
    }



} catch (RuntimeException $e) {

    echo $e->getMessage();

}

So everything seems to be ok but server drop the connection after something wrong (I don't think is related to PDOquery cause a smaller file of 2MB will work).

Could you please help identify the problem?

EDIT Doing some tests i've found that the script drop exactly at 30 second of execution, i've tryed to add set_time_limit(0); in top of the script but nothing changed again

andreaem
  • 1,635
  • 2
  • 20
  • 49
  • Well, some of your cases are missing breaks for them. This might not fix your code but you need to add those in. – Funk Forty Niner Sep 23 '17 at 13:11
  • *"I don't think is related to PDOquery"* - It might be, your `VALUES (NULL, '0', '0', '0', $fileName)` that filename is most likely a string and could be failing, yet I could be wrong though. – Funk Forty Niner Sep 23 '17 at 13:13
  • can you edit your post so that it contains the html for this? Maybe there's something in there that contains a restriction. If you're running this on your local server, make sure you restarted all services after making those changes, if you did make any changes that is. Set max exec time to 0 also. – Funk Forty Niner Sep 23 '17 at 13:17
  • @Fred-ii- The PDOquery doesn't affect the upload cause will be executed after this, It fails I know, but upload of a smaller file will work instead. I can paste the generated HTML for this but is the default HTML for Dropzone.js – andreaem Sep 23 '17 at 13:24
  • @ßiansorÅ.Ålmerol As I've written two times in the answer the error is that PHP drops the connection after approximately 4MB of upload or undefined time. Anyway maybe the problem is related to Drozone.js that reject the file – andreaem Sep 23 '17 at 13:25
  • Please see [my first comment](https://stackoverflow.com/questions/46379917/dropzone-js-upload-with-php-failed-after-4mb-upload?noredirect=1#comment79718265_46379917) again and try it again. – Funk Forty Niner Sep 23 '17 at 13:25
  • @Fred-ii- updated code adding `break;` as suggested but behaviour doesn't change. – andreaem Sep 23 '17 at 13:30
  • see if error reporting picks up anything – Funk Forty Niner Sep 23 '17 at 14:06
  • @Fred-ii- problem is that error.log doesn't list anything about this. – andreaem Sep 23 '17 at 14:21

2 Answers2

73

Problem was in XHR timeout referred to ajax call configuration.

To avoid this, must to put timeout: 180000(or what you want in ms) in the DropZone.js init parameters.

$("#dZUpload").dropzone({
     url: "/ajax/admin/admin.acceptVideo.php",
     maxFilesize: 209715200,
     acceptedFiles: "video/*",
     addRemoveLinks: true,
     dataType: "HTML",
     timeout: 180000,
     success: function (file, response, data) {
         // Do things on Success
     },
     error: function (file, response) {
     file.previewElement.classList.add("dz-error");
     }
});

This will not cause the 30 seconds timeout when uploading file with DropZone.js.

UPDATE

As @Brendon Muir reported, You can also insert 0 as timeout to disable the timeout.

The DropZone.js Documentation reports that the default timeout is 0, that's incorrect, the default timeout is 30 seconds. A value of 0 will disable the timeout.

Brendon Muir
  • 4,540
  • 2
  • 33
  • 55
andreaem
  • 1,635
  • 2
  • 20
  • 49
  • 1
    There are also settings at the web server level which might affect the timeout behavior. This one helped me: https://stackoverflow.com/questions/24127601/uwsgi-request-timeout-in-python – Alex Dong Nov 30 '17 at 18:27
  • 5
    You can also just set timeout to 0 to disable the timeout. It's incorrectly reported as 0 by default in the documentation but is actually set to 30 seconds by default. – Brendon Muir Jan 21 '18 at 20:35
  • 1
    Thanks for your suggestion @BrendonMuir, I've update my reply. – andreaem Jan 22 '18 at 19:46
  • 2
    Thanks man this is working i have to use 0 incase of uploading bigger files. – MR_AMDEV Apr 20 '19 at 10:04
  • 1
    had the same problem and your answer came up with the solution – Renato Ramos Puma May 07 '19 at 03:09
  • 1
    Proud of that! @RenatoRamosPuma – andreaem Jul 23 '19 at 22:12
  • Working perfectly. Thank you @andreaem – W.M. Aug 22 '19 at 21:13
  • Why on earth the developer of Dropzone would choose to set the default value to `30 seconds`, and log nothing to the console, and throw no exceptions, and simply fail silently is beyond me. I just, by chance of matching search terms, came across this answer. Thank you for saving me a lot of time. I was suspicious when there was no response at all from the server, and absolutely nothing indicative in the logs. I don't think I would have been able to make the mental jump to check out the bloody file upload library - of all things! – thephpdev Sep 06 '19 at 14:35
  • This saved a lot of headscratching! Nice answer. – IncredibleHat Mar 17 '20 at 02:43
1

I realise this question is a little old but I have had issues with catching the timeout behaviour and discovered this solution instead where the timeout is caught on the sending function as shown below:

$("#dZUpload").dropzone({
     url: "/ajax/admin/admin.acceptVideo.php",
     maxFilesize: 209715200,
     acceptedFiles: "video/*",
     addRemoveLinks: true,
     dataType: "HTML",
     data: { id: '' },
     success: function (file, response, data) {
         var imgName = response;
         file.previewElement.classList.add("dz-success");
         $('#form_video').val(imgName);
     },
     error: function (file, response) {
         file.previewElement.classList.add("dz-error");
     },
     //Called just before each file is sent
     sending: function(file, xhr, formData) {
         //Execute on case of timeout only
         xhr.ontimeout = function(e) {
             //Output timeout error message here
             console.log('Server Timeout');

         };
     }
});
karen
  • 893
  • 2
  • 13
  • 38