上传 30 秒后,使用 PHP 上传 Dropzone.js 失败

Posted

技术标签:

【中文标题】上传 30 秒后,使用 PHP 上传 Dropzone.js 失败【英文标题】:Dropzone.js upload with PHP failed after 30 seconds upload 【发布时间】:2018-03-04 22:19:45 【问题描述】:

我正在尝试将“大”文件上传到我的应用程序。用户必须能够上传小于 200MB 的视频文件,但似乎服务器在 4MB 或 30 秒后断开连接并且上传失败。

我已经将php.inifile 中的所有参数设置为:

max_input_time = 320max_execution_time = 320max_file_uploads = 20memory_limit = 512Mpost_max_size = 201Mupload_max_filesize = 200M

当我上传 2MB @ 1Mbps/s 的文件时一切正常(我不知道是文件大小还是传输时间的问题)

可以在 php_info 访问实时 php_info() 文件

虽然这里是 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";

这是处理上传的 PHP 脚本:

<?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();


所以一切似乎都正常,但服务器在出现问题后断开连接(我认为与PDOquery 无关,因为较小的 2MB 文件可以工作)。

您能帮忙找出问题吗?

编辑做一些测试,我发现脚本正好在执行 30 秒时下降,我尝试在脚本顶部添加 set_time_limit(0);,但没有任何改变

【问题讨论】:

好吧,您的一些案例缺少休息时间。这可能无法修复您的代码,但您需要添加它们。 “我认为与 PDOquery 无关” - 可能是,您的 VALUES (NULL, '0', '0', '0', $fileName) 文件名很可能是一个字符串并且可能会失败,但我可以不过是错的。 您可以编辑您的帖子以使其包含相应的 html 吗?也许那里有一些包含限制的东西。如果您在本地服务器上运行此程序,请确保在进行这些更改后重新启动所有服务(如果您确实进行了任何更改)。将最大执行时间也设置为 0。 @Fred-ii- PDOquery 不影响上传原因将在此之后执行,我知道它失败了,但是可以上传较小的文件。我可以为此粘贴生成的 HTML,但它是 Dropzone.js 的默认 HTML @ßiansorÅ.Ålmerol 正如我在答案中写过两次,错误是 PHP 在大约 4MB 上传或未定义时间后断开连接。无论如何,问题可能与拒绝文件的 Drozone.js 有关 【参考方案1】:

问题在于 XHR 超时涉及 ajax 调用配置。

为避免这种情况,必须将timeout: 180000(或您想要的毫秒数)放入DropZone.js init 参数中。

$("#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");
     
);

这不会在使用DropZone.js 上传文件时导致30 seconds 超时。

更新

正如@Brendon Muir 报告的那样,您还可以将0 插入为timeout 以禁用超时。

DropZone.js 文档报告默认超时为 0,这是不正确的,默认超时为 30 秒。 值为 0 将禁用超时。

【讨论】:

Web 服务器级别的设置也可能会影响超时行为。这个帮助了我:***.com/questions/24127601/… 您也可以将超时设置为 0 以禁用超时。它在文档中默认错误地报告为 0,但实际上默认设置为 30 秒。 感谢您的建议@BrendonMuir,我已经更新了我的回复。 谢谢伙计,这正在工作我必须使用 0 以防上传更大的文件。 遇到了同样的问题,你的回答想出了解决方案【参考方案2】:

我意识到这个问题有点老了,但是我在捕捉超时行为方面遇到了问题,并发现了这个解决方案,而不是在发送函数上捕捉到超时,如下所示:

$("#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');

         ;
     
);

【讨论】:

非常正确!对我来说,超时永远不会被错误回调捕获!虽然看起来像一个错误 我添加了发送: - 没有变化 - 只是服务器响应 0 代码。

以上是关于上传 30 秒后,使用 PHP 上传 Dropzone.js 失败的主要内容,如果未能解决你的问题,请参考以下文章

2020/1/30 PHP代码审计之文件上传漏洞

Dropzone - 未捕获的错误:未提供 URL

修改PHP上传文件大小限制

如何设置php上传文件大小限制

怎么修改php上传文件文件大小限制

怎么修改php上传文件文件大小限制第一次