Dropzone.js upload with PHP failed after 30 seconds upload
Asked Answered
E

2

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

Entanglement answered 23/9, 2017 at 13:7 Comment(9)
Well, some of your cases are missing breaks for them. This might not fix your code but you need to add those in.Bottommost
"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.Bottommost
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.Bottommost
@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.jsEntanglement
@ß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 fileEntanglement
Please see my first comment again and try it again.Bottommost
@Fred-ii- updated code adding break; as suggested but behaviour doesn't change.Entanglement
see if error reporting picks up anythingBottommost
@Fred-ii- problem is that error.log doesn't list anything about this.Entanglement
E
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.

Entanglement answered 29/9, 2017 at 11:47 Comment(9)
There are also settings at the web server level which might affect the timeout behavior. This one helped me: #24128101Inexhaustible
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.Taka
Thanks for your suggestion @BrendonMuir, I've update my reply.Entanglement
Thanks man this is working i have to use 0 incase of uploading bigger files.Selaginella
had the same problem and your answer came up with the solutionHover
Proud of that! @RenatoRamosPumaEntanglement
Working perfectly. Thank you @EntanglementBrood
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!Relieve
This saved a lot of headscratching! Nice answer.Thievery
D
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');

         };
     }
});
Dog answered 22/11, 2018 at 11:44 Comment(2)
very right! For me, the timeout is never caught in the error callback! seems like a bug thoughPalmy
I added the sending: - no change - just Server responded with 0 code.Jehanna

© 2022 - 2024 — McMap. All rights reserved.