Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 我如何中止超过php最大上传量的文件上传?_Javascript_Php_Ajax_File Upload_Upload - Fatal编程技术网

Javascript 我如何中止超过php最大上传量的文件上传?

Javascript 我如何中止超过php最大上传量的文件上传?,javascript,php,ajax,file-upload,upload,Javascript,Php,Ajax,File Upload,Upload,当上传超过PHP设置允许的最大大小的文件时,通常会在我能够处理服务器端的响应之前上传整个文件 在php.ini中,我将最大帖子大小和最大上传大小设置为2MB。当我在上载表单中选择一个超过2MB的文件(也称为1GB文件)时,服务器仍会接受该文件,但我需要等待整个文件上载完毕,以便处理上载事件 现在,有趣的是,上传进度会话返回100%,允许我返回上传表单隐藏进度条的控制,再次显示上传表单和提交按钮,但是由于必须等待上传实际完成,我无法将响应返回给用户 对于我的项目,有3个部分: 上载表单-包含将上载

当上传超过PHP设置允许的最大大小的文件时,通常会在我能够处理服务器端的响应之前上传整个文件

在php.ini中,我将最大帖子大小和最大上传大小设置为2MB。当我在上载表单中选择一个超过2MB的文件(也称为1GB文件)时,服务器仍会接受该文件,但我需要等待整个文件上载完毕,以便处理上载事件

现在,有趣的是,上传进度会话返回100%,允许我返回上传表单隐藏进度条的控制,再次显示上传表单和提交按钮,但是由于必须等待上传实际完成,我无法将响应返回给用户

对于我的项目,有3个部分:

上载表单-包含将上载发布到“upload.php”隐藏iframe的代码,并在“upload\u progress.php”XHR上监视进度。 upload.php-这是负责接受文件的文件处理程序,然后根据文件类型、错误、成功等将响应提升回上载表单锁定到当前域和协议的跨帧脚本。 upload_progress.php-这只是读取php的uploadprogress模块提供的上传进度的会话数据。响应是一个整数。 问题是,如果上载太大,3将显示为已完成,而2将继续接受数据,直到整个文件上载完毕

我想知道的是,当它发生时,有没有任何方法可以立即检测到它,而不是100%依赖于JavaScript在上传之前检查文件大小,因为这可以绕过。我知道我可以在发送文件之前检查客户端,但是在javascript中实现客户端中止之前,如果文件太大,我希望实现适当的服务器端中止上传。也就是说,我不想依靠JavaScript来实现服务器安全文件类型、大小等

希望我把一切都解释清楚了。我已经在PHP中看到这个问题很多年了,当接收到的数据超过PHP.ini中设置的限制时,我很惊讶文件上传没有在服务器端自动中止

如果有不同,下面是我的PHP版本详细信息

PHP 5.6.17-0+deb8u1 (cli) (built: Jan 13 2016 09:10:12) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies
PHP FPM在我的apache配置中为PHP服务的是什么

PHP 5.6.17-0+deb8u1 (fpm-fcgi) (built: Jan 13 2016 09:10:13)
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies
    with the ionCube PHP Loader (enabled) + Intrusion Protection from ioncube24.com (unconfigured) v5.0.23, Copyright (c) 2002-2016, by ionCube Ltd.
    with Xdebug v2.3.3, Copyright (c) 2002-2015, by Derick Rethans
    with Zend OPcache v7.0.6-dev, Copyright (c) 1999-2015, by Zend Technologies
和Apache

Server version: Apache/2.4.10 (Debian)
Server built:   Nov 28 2015 14:05:48
Server's Module Magic Number: 20120211:37
Server loaded:  APR 1.5.1, APR-UTIL 1.5.4
Compiled using: APR 1.5.1, APR-UTIL 1.5.4
Architecture:   64-bit
Server MPM:     prefork
  threaded:     no
    forked:     yes (variable process count)
Server compiled with....
 -D APR_HAS_SENDFILE
 -D APR_HAS_MMAP
 -D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
 -D APR_USE_SYSVSEM_SERIALIZE
 -D APR_USE_PTHREAD_SERIALIZE
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D APR_HAS_OTHER_CHILD
 -D AP_HAVE_RELIABLE_PIPED_LOGS
 -D DYNAMIC_MODULE_LIMIT=256
 -D HTTPD_ROOT="/etc/apache2"
 -D SUEXEC_BIN="/usr/lib/apache2/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache2.pid"
 -D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
 -D DEFAULT_ERRORLOG="logs/error_log"
 -D AP_TYPES_CONFIG_FILE="mime.types"
 -D SERVER_CONFIG_FILE="apache2.conf"

使用Javascript并在上传文件之前检查文件大小,尽管这不是如何从服务器端中止mid上传的示例

下面是一个活生生的例子:

JS在这里:

document.forms[0].addEventListener('submit', function( evt ) {

    var file = document.getElementById('file').files[0];

    // 1 MB = 1048576 this size is in bytes
    if(file && file.size < 2097152) {     // 2MB = 2097152

        //Submit form  
        document.getElementById('message').innerHTML = 'The File '+bytesToSize(file.size)+' is OK!';

    } 
    else 
    {

        //Prevent default and display error
        document.getElementById('message').innerHTML = 'The File '+bytesToSize(file.size)+' is to big!';
        evt.preventDefault();

    }
}, false);

function bytesToSize(bytes) {
   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
   if (bytes == 0) return '0 Bytes';
   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}

您确定在点击php upload_max_filesize之前上传了整个文件吗?web服务器将上传传递到PHP应用程序,PHP在处理上传之前不知道文件大小。是的,我100%确定。等待时间与文件传输持续时间成正比。例如,在我的网络上,1GB大约需要20分钟,之后,我会从upload.php脚本得到响应,但不是在之前。-但是我不知道它要去哪里。我认为只是在内存中,但不知道。我相信这可以通过一个简单的上传表单相当容易地复制,没有什么像modsec/etc那样会干扰本机上传操作。如果你说的是真的,那么这将是一个毫无意义的限制,所以我无法想象这会是一个PHP问题,web服务器可能正在对其进行缓冲,直到将其传递给PHP。您的web服务器设置是什么web服务器发行版、版本、PHP API在我的问题中添加了web服务器详细信息和PHP版本。我实际上使用的是php5 fpm,但是版本和编译是相同的,配置在重要的地方是相同的。谢谢你的回答,但是我已经熟悉如何使用JavaScript进行这些检查。这并不能阻止攻击者直接将文件推送到表单中,也就是说,如果接收的数据超过X数量,服务器端需要实际工作并停止数据上传。正如我在文章中所说,上传进度会得到通知,但是服务器会继续接收文件,直到文件完成后才返回控制。您还可以在Flash/Java/etc中检查上载大小/etc。仅依靠客户端来确保满足限制是一个劣质的解决方案。请不要误会,您提供的是非常好的客户端验证,假设启用了JavaScript,并且没有强制进行攻击。试想一下,表单上发生了一次不错的DoS攻击,仅使用100个客户端将1GB垃圾数据上传到100MB服务器连接,最大速度约为20 MB/秒。由于服务器仍将接受整个文件,您可以看到它如何很容易地耗尽带宽/etc,而且速度非常快。
document.forms[0].addEventListener('submit', function( evt ) {

    var file = document.getElementById('file').files[0];

    // 1 MB = 1048576 this size is in bytes
    if(file && file.size < 2097152) {     // 2MB = 2097152

        //Submit form  
        document.getElementById('message').innerHTML = 'The File '+bytesToSize(file.size)+' is OK!';

    } 
    else 
    {

        //Prevent default and display error
        document.getElementById('message').innerHTML = 'The File '+bytesToSize(file.size)+' is to big!';
        evt.preventDefault();

    }
}, false);

function bytesToSize(bytes) {
   var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
   if (bytes == 0) return '0 Bytes';
   var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
   return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}