Je travaille sur un formulaire PHP qui joint un fichier à un e-mail, et j'essaie de gérer avec élégance les cas où le fichier téléchargé est trop volumineux.
J'ai appris qu'il existe deux paramètres dans php.ini
qui affectent la taille maximale d'un téléchargement de fichier: upload_max_filesize
et post_max_size
.
Si la taille d'un fichier dépasse upload_max-filesize
, PHP renvoie la taille du fichier à 0. C'est très bien, je peux vérifier cela.
Mais s'il dépasse post_max_size
, mon script échoue en silence et revient au formulaire vierge.
Existe-t-il un moyen de détecter cette erreur?
De la documentation :
Si la taille des données de publication est supérieure à post_max_size, les $ _ POST et $ _FILES superglobals sont vides . Cela peut être suivi de différentes manières, par ex. en transmettant la variable $ _GET au script traitant les données, c'est-à-dire <form action = "edit.php? traitées = 1">, puis en vérifiant si $ _GET ['traitées'] est défini.
Donc, malheureusement, il ne ressemble pas à PHP envoie une erreur. Et comme il envoie un tableau $ _POST vide, c'est pourquoi votre script revient au formulaire vierge - il ne le fait pas pense que c'est un POST. (Assez mauvaise décision de conception à mon humble avis)
Ce commentateur a également une idée intéressante.
Il semble qu'une méthode plus élégante soit la comparaison entre post_max_size et $ _SERVER ['CONTENT_LENGTH']. Veuillez noter que ce dernier inclut non seulement la taille du fichier téléchargé plus les données de publication, mais également les séquences en plusieurs parties.
il existe un moyen d'attraper/gérer les fichiers dépassant la taille maximale du message, c'est mon préféré, car il indique à l'utilisateur final ce qui s'est passé et qui est en faute;)
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...
}
Nous avons eu le problème pour SOAP requêtes où une vérification de la vacuité de $ _POST et $ _FILES ne fonctionne pas, car elles sont également vides sur les demandes valides.
Par conséquent, nous avons implémenté une vérification, en comparant CONTENT_LENGTH et post_max_size. L'exception levée est ensuite transformée en XML-SOAP-FAULT par notre gestionnaire d'exceptions enregistré.
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;
}
En s'appuyant sur les réponses de @Matt McCormick et @ AbdullahAJM, voici un cas de test PHP qui vérifie que les variables utilisées dans le test sont définies, puis vérifie si $ _SERVER ['CONTENT_LENGTH'] dépasse la valeur php_max_filesize réglage:
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>';
}
}
C'est un moyen simple de résoudre ce problème:
Appelez simplement "checkPostSizeExceeded" au début de votre code
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.'
);
}
}
N'oubliez pas de copier cette fonction auxiliaire:
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;
}