Надеюсь, кто-то может ответить на мой вопрос.
У меня есть базовая форма, которая содержит простые поля, такие как имя, номер, адрес электронной почты и т. Д. И поле для загрузки файлов.
Я пытаюсь добавить некоторые проверки в мой скрипт, который определяет, является ли файл слишком большим, а затем отклоняет пользователя обратно в форму, чтобы выбрать / загрузить файл меньшего размера.
Моя проблема заключается в том, что, если пользователь выбирает файл, размер которого больше моего правила размера файла проверки и больше, чем 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>
. Когда действие отправки принимается в любой форме, отмените действие по умолчанию и вместо этого выполните одну из двух вещей:
Вы можете попытаться посмотреть, можете ли вы прочитать что-либо из 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'); }