Estoy trabajando en un formulario PHP que adjunta un archivo a un correo electrónico y trato de manejar con elegancia los casos en los que el archivo cargado es demasiado grande.
Aprendí que hay dos configuraciones php.ini
que afectan el tamaño máximo de la carga de un archivo: upload_max_filesize
y post_max_size
.
Si el tamaño de un archivo excede upload_max_filesize
, PHP devuelve el tamaño del archivo como 0. Eso está bien; Puedo comprobar eso.
Pero si excede post_max_size
, mi script falla silenciosamente y vuelve al formulario en blanco.
¿Hay alguna forma de detectar este error?
Respuestas:
De la documentación :
Entonces, desafortunadamente, no parece que PHP envíe un error. Y dado que envía una matriz $ _POST vacía, es por eso que su script está volviendo al formulario en blanco, no cree que sea una POST. (En mi humilde opinión, una decisión de diseño bastante pobre)
Este comentarista también tiene una idea interesante.
fuente
hay una forma de capturar / manejar archivos que exceden el tamaño máximo de publicación, esta es mi preferencia, ya que le dice al usuario final lo que sucedió y quién tiene la culpa;)
if (empty($_FILES) && empty($_POST) && isset($_SERVER['REQUEST_METHOD']) && strtolower($_SERVER['REQUEST_METHOD']) == 'post') { //catch file overload error... $postMax = ini_get('post_max_size'); //grab the size limits... echo "<p style=\"color: #F00;\">\nPlease note files larger than {$postMax} will result in this error!<br>Please be advised this is not a limitation in the CMS, This is a limitation of the hosting server.<br>For various reasons they limit the max size of uploaded files, if you have access to the php ini file you can fix this by changing the post_max_size setting.<br> If you can't then please ask your host to increase the size limits, or use the FTP uploaded form</p>"; // echo out error and solutions... addForm(); //bounce back to the just filled out form. } else { // continue on with processing of the page... }
fuente
$_SERVER['CONTENT_LENGTH']
yupload_max_filesize
en cuenta.Tenemos el problema de las solicitudes SOAP en las que una verificación de vacío de $ _POST y $ _FILES no funciona, porque también están vacíos en solicitudes válidas.
Por lo tanto, implementamos una verificación, comparando CONTENT_LENGTH y post_max_size. La excepción lanzada se transforma más tarde en un XML-SOAP-FAULT por nuestro controlador de excepciones registrado.
private function checkPostSizeExceeded() { $maxPostSize = $this->iniGetBytes('post_max_size'); if ($_SERVER['CONTENT_LENGTH'] > $maxPostSize) { throw new Exception( sprintf('Max post size exceeded! Got %s bytes, but limit is %s bytes.', $_SERVER['CONTENT_LENGTH'], $maxPostSize ) ); } } private function iniGetBytes($val) { $val = trim(ini_get($val)); if ($val != '') { $last = strtolower( $val{strlen($val) - 1} ); } else { $last = ''; } switch ($last) { // The 'G' modifier is available since PHP 5.1.0 case 'g': $val *= 1024; // fall through case 'm': $val *= 1024; // fall through case 'k': $val *= 1024; // fall through } return $val; }
fuente
Sobre la base de las respuestas de @Matt McCormick y @ AbdullahAJM, aquí hay un caso de prueba de PHP que verifica que las variables utilizadas en la prueba estén configuradas y luego verifica si $ _SERVER ['CONTENT_LENGTH'] excede la configuración de php_max_filesize:
if ( isset( $_SERVER['REQUEST_METHOD'] ) && ($_SERVER['REQUEST_METHOD'] === 'POST' ) && isset( $_SERVER['CONTENT_LENGTH'] ) && ( empty( $_POST ) ) ) { $max_post_size = ini_get('post_max_size'); $content_length = $_SERVER['CONTENT_LENGTH'] / 1024 / 1024; if ($content_length > $max_post_size ) { print "<div class='updated fade'>" . sprintf( __('It appears you tried to upload %d MiB of data but the PHP post_max_size is %d MiB.', 'csa-slplus'), $content_length, $max_post_size ) . '<br/>' . __( 'Try increasing the post_max_size setting in your php.ini file.' , 'csa-slplus' ) . '</div>'; } }
fuente
Esa es una forma sencilla de solucionar este problema:
Simplemente llame a "checkPostSizeExceeded" al comienzo de su código
function checkPostSizeExceeded() { if (isset($_SERVER['REQUEST_METHOD']) and $_SERVER['REQUEST_METHOD'] == 'POST' and isset($_SERVER['CONTENT_LENGTH']) and empty($_POST)//if is a post request and $_POST variable is empty(a symptom of "post max size error") ) { $max = get_ini_bytes('post_max_size');//get the limit of post size $send = $_SERVER['CONTENT_LENGTH'];//get the sent post size if($max < $_SERVER['CONTENT_LENGTH'])//compare throw new Exception( 'Max size exceeded! Were sent ' . number_format($send/(1024*1024), 2) . 'MB, but ' . number_format($max/(1024*1024), 2) . 'MB is the application limit.' ); } }
Recuerde copiar esta función auxiliar:
function get_ini_bytes($attr){ $attr_value = trim(ini_get($attr)); if ($attr_value != '') { $type_byte = strtolower( $attr_value{strlen($attr_value) - 1} ); } else return $attr_value; switch ($type_byte) { case 'g': $attr_value *= 1024*1024*1024; break; case 'm': $attr_value *= 1024*1024; break; case 'k': $attr_value *= 1024; break; } return $attr_value; }
fuente