Данные $ _POST возвращаются пустым, если заголовки> POST_MAX_SIZE

Надеюсь, кто-то может ответить на мой вопрос.

У меня есть базовая форма, которая содержит простые поля, такие как имя, номер, адрес электронной почты и т. Д. И поле для загрузки файлов.

Я пытаюсь добавить некоторые проверки в мой скрипт, который определяет, является ли файл слишком большим, а затем отклоняет пользователя обратно в форму, чтобы выбрать / загрузить файл меньшего размера.

Моя проблема заключается в том, что, если пользователь выбирает файл, размер которого больше моего правила размера файла проверки и больше, чем php.ini POST_MAX_SIZE / UPLOAD_MAX_FILESIZE, и толкает submit, то PHP, похоже, пытается обработать форму только с ошибкой в ​​настройках POST_MAX_SIZE, а затем очищает весь массив $ _POST и ничего не возвращает в форму.

Есть ли способ обойти это? Конечно, если кто-то загружает что-то>, чем максимальный размер, настроенный в php.ini, тогда вы все равно можете получить остальную часть данных $ _POST ???

Вот мой код.

<?php function validEmail($email) { $isValid = true; $atIndex = strrpos($email, "@"); if (is_bool($atIndex) && !$atIndex) { $isValid = false; } else { $domain = substr($email, $atIndex+1); $local = substr($email, 0, $atIndex); $localLen = strlen($local); $domainLen = strlen($domain); if ($localLen < 1 || $localLen > 64) { // local part length exceeded $isValid = false; } else if ($domainLen < 1 || $domainLen > 255) { // domain part length exceeded $isValid = false; } else if ($local[0] == '.' || $local[$localLen-1] == '.') { // local part starts or ends with '.' $isValid = false; } else if (preg_match('/\\.\\./', $local)) { // local part has two consecutive dots $isValid = false; } else if (!preg_match('/^[A-Za-z0-9\\-\\.]+$/', $domain)) { // character not valid in domain part $isValid = false; } else if (preg_match('/\\.\\./', $domain)) { // domain part has two consecutive dots $isValid = false; } else if (!preg_match('/^(\\\\.|[A-Za-z0-9!#%&`_=\\/$\'*+?^{}|~.-])+$/', str_replace("\\\\","",$local))) { // character not valid in local part unless // local part is quoted if (!preg_match('/^"(\\\\"|[^"])+"$/', str_replace("\\\\","",$local))) { $isValid = false; } } } return $isValid; } //setup post variables @$name = htmlspecialchars(trim($_REQUEST['name'])); @$emailCheck = htmlspecialchars(trim($_REQUEST['email'])); @$organisation = htmlspecialchars(trim($_REQUEST['organisation'])); @$title = htmlspecialchars(trim($_REQUEST['title'])); @$phone = htmlspecialchars(trim($_REQUEST['phone'])); @$location = htmlspecialchars(trim($_REQUEST['location'])); @$description = htmlspecialchars(trim($_REQUEST['description'])); @$fileError = 0; @$phoneError = ""; //setup file upload handler $target_path = 'uploads/'; $filename = basename( @$_FILES['uploadedfile']['name']); $max_size = 8000000; // maximum file size (8mb in bytes) NB: php.ini max filesize upload is 10MB on test environment. $allowed_filetypes = Array(".pdf", ".doc", ".zip", ".txt", ".xls", ".docx", ".csv", ".rtf"); //put extensions in here that should be uploaded only. $ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename. if(!is_writable($target_path)) die('You cannot upload to the specified directory, please CHMOD it to 777.'); //Check if we can upload to the specified upload folder. //display form function function displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError) { //make $emailCheck global so function can get value from global scope. global $emailCheck; global $max_size; echo '<form action="geodetic_form.php" method="post" name="contact" id="contact" enctype="multipart/form-data">'."\n". '<fieldset>'."\n".'<div>'."\n"; //name echo '<label for="name"><span class="mandatory">*</span>Your name:</label>'."\n". '<input type="text" name="name" id="name" class="inputText required" value="'. $name .'" />'."\n"; //check if name field is filled out if (isset($_REQUEST['submit']) && empty($name)) { echo '<label for="name" class="error">Please enter your name.</label>'."\n"; } echo '</div>'."\n". '<div>'."\n"; //Email echo '<label for="email"><span class="mandatory">*</span>Your email:</label>'."\n". '<input type="text" name="email" id="email" class="inputText required email" value="'. $emailCheck .'" />'."\n"; // check if email field is filled out and proper format if (isset($_REQUEST['submit']) && validEmail($emailCheck) == false) { echo '<label for="email" class="error">Invalid email address entered.</label>'."\n"; } echo '</div>'."\n". '<div>'."\n"; //organisation echo '<label for="phone">Organisation:</label>'."\n". '<input type="text" name="organisation" id="organisation" class="inputText" value="'. $organisation .'" />'."\n"; echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n"; //title echo '<label for="phone">Title:</label>'."\n". '<input type="text" name="title" id="title" class="inputText" value="'. $title .'" />'."\n"; echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n"; //phone echo '<label for="phone"><span class="mandatory">*</span>Phone <br /><span class="small">(include area code)</span>:</label>'."\n". '<input type="text" name="phone" id="phone" class="inputText required" value="'. $phone .'" />'."\n"; // check if phone field is filled out that it has numbers and not characters if (isset($_REQUEST['submit']) && $phoneError == "true" && empty($phone)) echo '<label for="email" class="error">Please enter a valid phone number.</label>'."\n"; echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n"; //Location echo '<label class="location" for="location"><span class="mandatory">*</span>Location:</label>'."\n". '<textarea name="location" id="location" class="required">'. $location .'</textarea>'."\n"; //check if message field is filled out if (isset($_REQUEST['submit']) && empty($_REQUEST['location'])) echo '<label for="location" class="error">This field is required.</label>'."\n"; echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n"; //description echo '<label class="description" for="description">Description:</label>'."\n". '<textarea name="description" id="queryComments">'. $description .'</textarea>'."\n"; echo '</div>'."\n". '</fieldset>'."\n".'<fieldset>'. "\n" . '<div>'."\n"; //file upload echo '<label class="uploadedfile" for="uploadedfile">File:</label>'."\n". '<input type="file" name="uploadedfile" id="uploadedfile" value="'. $filename .'" />'."\n"; // Check if the filetype is allowed, if not DIE and inform the user. switch ($fileError) { case "1": echo '<label for="uploadedfile" class="error">The file you attempted to upload is not allowed.</label>'; break; case "2": echo '<label for="uploadedfile" class="error">The file you attempted to upload is too large.</label>'; break; } echo '</div>'."\n". '</fieldset>'; //end of form echo '<div class="submit"><input type="submit" name="submit" value="Submit" id="submit" /></div>'. '<div class="clear"><p><br /></p></div>'; } //end function //setup error validations if (isset($_REQUEST['submit']) && !empty($_REQUEST['phone']) && !is_numeric($_REQUEST['phone'])) $phoneError = "true"; if (isset($_REQUEST['submit']) && $_FILES['uploadedfile']['error'] != 4 && !in_array($ext, $allowed_filetypes)) $fileError = 1; if (isset($_REQUEST['submit']) && $_FILES["uploadedfile"]["size"] > $max_size) $fileError = 2; echo "this condition " . $fileError; $POST_MAX_SIZE = ini_get('post_max_size'); $mul = substr($POST_MAX_SIZE, -1); $mul = ($mul == 'M' ? 1048576 : ($mul == 'K' ? 1024 : ($mul == 'G' ? 1073741824 : 1))); if ($_SERVER['CONTENT_LENGTH'] > $mul*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) echo "too big!!"; echo $POST_MAX_SIZE; if(empty($name) || empty($phone) || empty($location) || validEmail($emailCheck) == false || $phoneError == "true" || $fileError != 0) { displayForm($name, $emailCheck, $organisation, $phone, $title, $location, $description, $phoneError, $allowed_filetypes, $ext, $filename, $fileError); echo $fileError; echo "max size is: " .$max_size; echo "and file size is: " . $_FILES["uploadedfile"]["size"]; exit; } else { //copy file from temp to upload directory $path_of_uploaded_file = $target_path . $filename; $tmp_path = $_FILES["uploadedfile"]["tmp_name"]; echo $tmp_path; echo "and file size is: " . filesize($_FILES["uploadedfile"]["tmp_name"]); exit; if(is_uploaded_file($tmp_path)) { if(!copy($tmp_path,$path_of_uploaded_file)) { echo 'error while copying the uploaded file'; } } //test debug stuff echo "sending email..."; exit; } ?> 

PHP возвращает эту ошибку в журнале: [29-Apr-2010 10:32:47] PHP Warning: POST Content-Length из 57885895 байт превышает предел 10485760 байт в Unknown в строке 0

Извините все отладочные вещи 🙂

FTR, я запускаю PHP 5.1.2 в IIS.

PHP выкидывает все данные POST, потому что не было места для его размещения. Нет ничего надежного, что можно было бы получить только от части данных.

Я бы обошел эту проблему, загрузив необходимые файлы на отдельном шаге, в другой форме. Вы можете сохранить значения, уже полученные в сеансе, гарантируя, что они не будут потеряны из-за чрезмерных данных POST.

Эриско прав, это нужно разбить на несколько этапов. Однако я не верю, что есть необходимость разоблачить эту внутреннюю разметку для пользователя, поэтому я бы рекомендовал один из следующих способов:

Перерыв загрузки файла в отдельный элемент <form> . Когда действие отправки принимается в любой форме, отмените действие по умолчанию и вместо этого выполните одну из двух вещей:

  1. Отправьте регулярные данные формы через AJAX, и когда это будет завершено, отправьте загруженный файл с помощью стандартного процесса (включая перезагрузку страницы и что-нет)
  2. Проверьте этот пример обмана iFrame, чтобы загрузить файл в первую очередь, убедитесь, что он не слишком велик, и не допускайте перезагрузки страницы, если она иначе не пройдет. Если файл проходит, сохраните его идентификатор в скрытом элементе ввода и отправьте форму в обычном режиме. Возьмите любое действие, если файл не загружается правильно. Обратите внимание, что это решение не требует от вас использования сеанса PHP, всего лишь немного обмана.

Вы можете попытаться посмотреть, можете ли вы прочитать что-либо из php://input или php://stdin после того, как вы обнаружите, что массив _POST запущен. Вы можете получить данные POST оттуда и обработать его вручную, но в руководстве также говорится, что это не будет работать для //input если ваша форма использует enctype=multipart/form-data

«Попробуйте переместить поле файла в нижнюю часть формы и посмотреть, что произойдет. – Марк Б»

К сожалению, это происходит: массив $_POST очищается. Таким образом, обход iFrame является одним из лучших решений. Спасибо за это, Dereleased !

один из трюков – использовать что-то вроде этого:

 $lE = error_get_last(); if ( !empty($lE) && strpos($lE['message'] , 'POST Content-Length' ) !== false) { die ('Naughty naughty. you can only upload xxxxx bytes'); }