2010-01-25 11 views
74

Pracuję nad formularzem PHP, który dołącza plik do wiadomości e-mail i próbuje zręcznie obsługiwać przypadki, w których przesłany plik jest zbyt duży.Jak z wdziękiem obsługiwać pliki przekraczające "post_max_size" PHP?

Dowiedziałem się, że istnieją dwa ustawienia w php.ini, które wpływają na maksymalny rozmiar pliku do przesłania: upload_max_filesize i post_max_size.

Jeśli rozmiar pliku przekracza upload_max-filesize, PHP zwraca rozmiar pliku jako 0. To dobrze; Mogę to sprawdzić.

Ale jeśli przekracza on post_max_size, mój skrypt nie działa po cichu i wraca do pustego formularza.

Czy istnieje sposób na złapanie tego błędu?

+1

masz dostęp do php.ini? Post_max_size powinno być większe niż upload_max_filesize. Powinieneś także używać w formularzu jak opisano http://ca2.php.net/manual/en/features.file-upload.post -method.php –

+0

@Matt McCormick - wejście MAX_FILE_SIZE działa świetnie - jeśli rozmiar pliku przekracza ten rozmiar, rozmiar pliku pokazuje się teraz jako 0, co jest przypadkiem, w którym już zostałem obsłużony. Mimo że może to zostać ominięte przez złośliwego użytkownika, służy on moim celom tutaj, ponieważ po prostu próbuję zawodzić z wdziękiem dla zwykłych użytkowników. –

Odpowiedz

47

Od the documentation:

Jeżeli rozmiar danych postu jest większa niż post_max_size, że $ _POST i $ _FILES Superglobale są puste. Ten może być śledzony na różne sposoby, na przykład przepuszczając zmiennej $ _GET do skryptu przetwarzanie danych, to jest < postać działań = „edit.php? Przetwarzane = 1”>, a następnie sprawdzenie, czy $ _ GET [ „przetworzone”] jest zestawu.

Niestety, nie wygląda na to, że PHP wysyła błąd. A ponieważ wysyła on pustą tablicę $ _POST, dlatego Twój skrypt powraca do pustej formy - nie sądzi, że jest to POST. (Zła decyzja dotycząca projektu IMHO)

This commenter ma również interesujący pomysł.

Wydaje się, że bardziej eleganckim sposobem jest porównanie między post_max_size i $ _SERVER [ '] CONTENT_LENGTH. Proszę pamiętać, że ta ostatnia zawiera nie tylko rozmiar przesłanego pliku oraz dane posta , ale także sekwencje wieloczęściowe.

+3

Proszę przeczytać pogrubioną część. To znaczy, jeśli rozmiar pliku przekracza upload_max_filesize, użytkownik pyta, co się stanie, gdy formularz przekroczy post_max_size. Post_max_size powinno być ustawione wyżej niż upload_max_filesize, aby spróbować uniknąć tego problemu, ale OP może mieć powody, aby zachować to samo. –

+1

Niestety, pomieszałem post_max_size i upload_max_filesize. +1 –

+0

@Matt - post_max_size Ustawiono wartość wyższą niż upload_max_filesize, ale nadal otrzymuję błąd, jeśli przesyłka przekracza oba. Jeśli mieści się między tymi dwoma, widzę, że rozmiar pliku pokazuje 0. –

36

istnieje sposób, aby złapać/obsługi plików przekraczających maksymalny rozmiar postu, to jest mój preferowany na, jak to mówi użytkownikowi końcowemu, co się stało i kto jest winy;)

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. 
} 
elseif(// continue on with processing of the page... 
+2

Działa to, gdy track_errors = Off, prawdopodobnie również display_errors = Off i display_startup_errors = Off w php.ini. W przeciwnym razie PHP nawet nie zajdzie tak daleko i wyśle ​​ostrzeżenie, jak w tytule pytania. Ale w systemie produkcyjnym powinno to być ustawienie php.ini, więc działa to świetnie. – raoulsson

+2

Ten zgrabny pomysł działa dobrze w moich testach (PHP/5.5.8). Można go również ulepszyć, biorąc pod uwagę '$ _SERVER ['CONTENT_LENGTH']' i 'upload_max_filesize'. –

+1

To jest poprawna odpowiedź. – Zulakis

6

Mamy dostałem problem z żądaniami SOAP, w których sprawdzanie pustki $ _POST i $ _FILES nie działa, ponieważ są one puste w przypadku prawidłowych żądań.

Dlatego zaimplementowaliśmy sprawdzanie, porównując CONTENT_LENGTH i post_max_size. Wyrzucony wyjątek jest później przekształcany w błąd XML-SOAP-FAULT przez naszą zarejestrowaną procedurę obsługi wyjątku.

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; 
} 
+0

@ manuel-azar: dodane elementy "break" nie są poprawne. te nie należą tam .. zobacz https://3v4l.org/ABfGs – staabm

2

Opierając się na @Matt McCormick i @ odpowiedzi AbdullahAJM, oto jest sprawdzianem PHP, który sprawdza zmienne użyte w teście są ustawione, a następnie sprawdza, czy $ _SERVER [ „CONTENT_LENGTH”] przekracza ustawienie 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>'; 
       } 
      } 
1

jest to prosty sposób na rozwiązanie tego problemu:

Wystarczy zadzwonić "checkPostSizeExceeded" on rozpocząć od kodu

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.' 
        ); 
     } 
    } 

Pamiętaj skopiować tę funkcję 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; 
} 
Powiązane problemy