2011-05-31 12 views
8

¿Cómo debo manejar cargas http que exceden el post_max_size de una manera sensata?¿Cómo detectar si un usuario subió un archivo más grande que post_max_size?

En mi configuración post_max_size es unos MB mayor que upload_max_filesize Los problemas que tengo son:
Si un usuario sube un archivo superior a post_max_size

  • La matriz está vacía _POST
  • Los HTTP_POST_FILES array está vacío y, por supuesto, los códigos de error no están presentes.
  • No hay otra información sobre qué tipo de formulario publicar es accesible a través de estos medios.

Parte del problema es que la secuencia de comandos de recepción toma diferentes acciones dependiendo del contenido de la POST.

que tienen acceso a los _SERVER las variables y pueden obtener pistas sobre lo que sucedió, es decir CONTENT_TYPE, CONTENT_LENGTH y REQUEST_METHOD. Sin embargo, parece muy problemático hacer conjeturas basadas en esos contenidos.

MEMORY_LIMIT (establecido en 10 veces los tamaños correspondientes) y Apaches LimitRequestBody (establecido en ilimitado) no tienen la culpa.

Tal como está ahora, me es difícil incluso proporcionarle mensajes significativos al usuario.

¿Hay alguna manera de retener algunos datos del formulario para obtener mejores pistas sobre lo que salió mal? Soy muy reacio a alejarme de php.

Respuesta

8

Para una solución simple que no requiera cambios en el servidor, utilizaría HTML5 File API para verificar el tamaño del archivo antes de cargarlo. Si excede el límite conocido, entonces cancele la carga. Creo que algo como esto funcionaría:

function on_submit() 
{ 
    if (document.getElementById("upload").files[0].size > 666) 
    { 
    alert("File is too big."); 
    return false; 
    } 

    return true; 
} 

<form onsubmit="return on_submit()"> 
<input id="upload" type="file" /> 
</form> 

Obviamente, es sólo un esqueleto de un ejemplo, y no cada navegador es compatible con esto. Pero no estaría de más utilizar esto, ya que podría implementarse de forma tal que se degrada graciosamente en nada para los navegadores más antiguos.

Por supuesto, esto no resuelve el problema, pero al menos mantendrá satisfechos a un número de usuarios con un mínimo esfuerzo. (Y ni siquiera tendrán que esperar a la carga falle.)

-

Como acotación al margen, la comprobación $_SERVER['CONTENT_LENGTH'] vs el tamaño de los datos de correos y archivos podrían ayudar a detectar si algo ha fallado. Creo que cuando hay un error será distinto de cero, mientras que $_POST y $_FILES estarán vacíos.

+0

Para ser claros, implementaría esto junto con algo como la cita en la respuesta de @King Skippus. es decir, utilice esta solución del lado del cliente para hacer felices a las personas, y luego busque la publicación vacía en el lado del servidor y actúe en consecuencia. – Matthew

+0

Esto es útil. Mi principal preocupación es no poder notificar a mis usuarios de manera adecuada. ¿Alguna idea sobre el soporte en los navegadores actuales? –

+1

@Captain Giraffe, creo que todos los navegadores no IE de uso común le permiten verificar el tamaño del archivo a través de JavaScript de esa manera, pero no estoy del todo seguro. (Y de nuevo, se degradará con gracia, por lo que no hay daño al usar esto como parte de su solución.) También, vea mi edición para una forma potencial de verificar si ocurrió un problema de carga. – Matthew

0

Es posible que tenga que volver a algo que utiliza el flash/Silverlight, etc., tales como: http://www.plupload.com/

o mirar hacia una solución basada en Java ...

Básicamente algo que va a romper la carga en trozos más manejables (y reanudables), y luego reensamblarlos en el lado del servidor.

0

A menos que su formulario de carga tenga campos que no sean el campo de entrada del archivo, entonces $ _POST debe estar vacío: los archivos se manejan exclusivamente a través de $ _FILES. Es muy extraño que $ _FILES esté vacío si se excede el tamaño de la publicación: los manejadores de carga tienen un código de error específico (1/UPLOAD_ERR_INI_SIZE) para informar tal condición. También verifique que memory_limit sea más grande que upload_max_filesize.

Su servidor web también puede estar bloqueando la carga, lo que ocurriría antes de invocar PHP. En Apache, está controlado por LimitRequestBody.

+0

Sí algunos otros campos que, en circunstancias normales están allí para identificar qué tipo de carga que es. LimitRequestBody está configurado muy por encima de la configuración de php en este caso y no interfiere. –

+0

Sí, yo también estoy muy sorprendido de encontrar los _FILES vacíos solo por esto. –

+0

¿Hay algo en los registros de errores de PHP y/o Apache? –

3

por la PHP documentation:

Si el tamaño de los datos de entrada es mayor que post_max_size, los $ _POST y $ _FILES superglobales están vacías. Esto se puede rastrear de varias maneras, p. pasando la variable $ _GET al script que procesa los datos, es decir, < form action = "edit.php? processed = 1" >, y luego verificando si $ _GET ['processed'] está configurado.

Si necesita el límite de aumento para una secuencia de comandos específicos, puede intentar ini_set ('post-max-size', $ size_needed) ;. Sin embargo, no estoy seguro si puede ser anulado dentro de un script; ese límite probablemente esté allí específicamente para evitar que hagas lo que intentas hacer.

+1

Estoy contento con mis límites, pero no con la forma en que php reacciona cuando se exceden esos límites. También la idea GET es útil, pero me gustaría que sea transparente para el usuario y se siente "hackosa". –

1

Me gustó la respuesta @Matthew, pero necesitaba una versión que verificara la carga de múltiples archivos.

Esta fue mi solución:

function checkAttachmentsSize() { 
    var total = 0; 
    var count = 0; 

    jQuery('input[type="file"]').each(
     function() { 
      if (typeof this.files[0] != 'undefined') { 
       total+= this.files[0].size; 
       count++; 
      } 
     } 
    ); 

    var word = (count > 1) ? 's are' : ' is'; 
    if (total > (uploadMax * 1000 * 1000)) { 
     alert("The attachment file" + word + " too large to upload."); 
     return false; 
    } 

    return true; 
} 

y como complemento, aquí está la unión de la función de la forma de ser enviada:

jQuery(function($) { 
    $("form").submit(
     function() { 
      return checkAttachmentsSize(); 
     } 
    }); 
); 

NOTA:
uploadMax es una variable que configuré vía php después de calcular el tamaño máximo de la carga permitida.

1

Puede resolver esto en el servidor sin recurrir a una cadena de consulta. Simplemente compare la configuración de * post_max_size * con la duración del contenido esperado de la solicitud. El siguiente código es cómo lo hace Kohana.

public static function post_max_size_exceeded() 
{ 
    // Make sure the request method is POST 
    if (Request::$initial->method() !== HTTP_Request::POST) 
     return FALSE; 

    // Get the post_max_size in bytes 
    $max_bytes = Num::bytes(ini_get('post_max_size')); 

    // Error occurred if method is POST, and content length is too long 
    return (Arr::get($_SERVER, 'CONTENT_LENGTH') > $max_bytes); 
} 
+0

No manejo la carga yo mismo. php lo hace. Si pudiera interceptar el "content_length" del navegador, todos serían unicornios rosas y mariposas. Aunque aprecio tu aporte. –

Cuestiones relacionadas