2009-05-14 19 views
37

Quiero permitir cargas de archivos muy grandes en nuestra aplicación PHP (cientos de megas - 8 gigas). Sin embargo, hay un par de problemas con esto.Cargas muy grandes con PHP

Navegador:

  • archivos HTML tienen retroalimentación de basura, tenemos que cualquiera sondeo para el progreso (que es un poco tonto) o mostrar ninguna reacción en absoluto
  • Flash Uploader pone archivo en la memoria antes de comenzar la carga

servidor:

  • PHP nos obliga a establecer post_max_size, w que podría resultar en un ataque de DOS fácilmente explotable. Me gustaría no establecer esta configuración globalmente.
  • El servidor también requiere que haya otras variables en los valores POST, como una clave secreta. Nos gustaría poder rechazar la solicitud de inmediato, en lugar de después de cargar todo el archivo.

Requisitos:

  • HTTP es una necesidad.
  • Soy flexible con la tecnología del lado del cliente, siempre que funcione en un navegador.
  • PHP no es un requisito, si hay alguna otra tecnología que funcione bien en un entorno Linux, eso está perfectamente bien.
+1

Si las partes internas de PHP no amortiguan la entrada completa, se podría escribir un módulo que va a revisar la ID en la cabecera antes de que el cuerpo de POST contra una base de datos. Ejecute el servidor especial en otro puerto, genere la ID de su servidor web principal. –

+0

¿Está indicando que Flash está fuera de la mesa porque lee el archivo completo en la memoria antes de comenzar la carga? (Solo aclarando) –

+0

Quiero ver qué sucede cuando muchos usuarios de la web cargan archivos de 8GB simultáneamente. –

Respuesta

3

¿Qué tal un applet de Java? Así es como tuvimos que hacerlo en una empresa para la que trabajé anteriormente. Sé que los applets apestan, especialmente en este día y edad, con todas nuestras opciones disponibles, pero en realidad son la solución más versátil para los problemas de escritorio que se encuentran en el desarrollo web. Solo algo a considerar.

+1

applet de java podría hacer el truco, pero eso es solo la mitad del problema. – Evert

+1

Wordpress usa un cargador basado en flash. –

1

¿Ha considerado utilizar APC para verificar el progreso y el tamaño total del archivo? Aquí hay un good blog post al respecto. Podría ayudar.

+0

El truco de APC requiere sondeo, que no me gusta debido a nuestro escenario de equilibrio de carga. – Evert

+0

¿No puede realizar sondeos porque cada solicitud de sondeo podría estar configurada en un servidor diferente de la iniciada la descarga? –

+0

podría almacenar la clave de sondeo en una base de datos –

1

Tal vez usted podría utilizar Webdav y Javascript en su navegador

AJAX Archivo grande de carga, con el progreso, a WebDAV

http://www.webdavsystem.com/ajax/programming/upload_progress

Una biblioteca simple

http://debris.demon.nl/projects/davclient.js/doc/README.html

A continuación, puede obtener el JS para redirigir al usuario a una página de éxito. Las claves secretas y lo que no se pueden manejar en un preludio de PHP antes de entregar el cliente JS-> WebDAV

+0

Javascript no me permitirá leer el contenido de un archivo local. No sé exactamente cómo lo hace 'webdavsystem', pero creo que simplemente siguen usando una carga estándar y tienen un controlador especial para eso en el servidor. – Evert

2

Puede establecer el tamaño de la pos_max para sólo las secuencias de comandos en 1 directorio. Coloque allí su script de carga y permita que solo ese script maneje tamaños grandes. Todavía es posible que ese script sea atacado con archivos grandes/inútiles, pero evita establecerlo globalmente.

uso que con APC y que podría ser capaz de averiguar algo bueno: IBM Developer works article on APC

+0

APC es difícil de usar en nuestra configuración de equilibrio de carga. No utilizamos la fijación de cookies, por lo que para utilizarla correctamente, necesitamos sondear el servidor real al que se carga el archivo (lo cual es una mierda en nuestra situación). Solo tener el directorio post_max_size en 1 tampoco me sirve, porque aún es susceptible a los ataques de DOS en ese 1 directorio, y quiero bloquear las solicitudes que contengan datos GET no válidos cuando se inicie .. – Evert

1

Me gustaría ver en FTP, SSH or SCP esto le permite cargar un archivo grande y aún así tener control de acceso sobre el archivo también. Esto podría demorar un poco más en implementarse, pero es probablemente la manera más segura en la que podría pensar.

+0

Nosotros No quiero ir realmente por esta ruta. HTTP es simple, así que no queremos complicar demasiado el entorno. Estamos abiertos a usar algo más que PHP en el lado del servidor, pero HTTP es imprescindible. – Evert

0

sé que aspira a añadir otra dependencia, pero en mi experiencia, la mayoría de los sitios web que están haciendo algo como esto están utilizando flash en el lado del cliente, y la posibilidad de subir el archivo grande como trozos

de adobe como howto on flash file uploads

también encontré este tutorial sobre CodeProject:

Multiple File Upload With Progress Bar Using Flash and ASP.NET

PS - sé que estás usando PHP y no NET, pensé que la parte importante era el flash;)

+0

Desafortunadamente, el flash ha sido problemático. Flash guarda todo el archivo en la memoria antes de cargarlo, lo que da como resultado una congelación total de mi Mac durante un par de minutos :( – Evert

+0

Me pregunto ... ¿es posible leer en trozos también? – Jiaaro

+0

La clase FileReference en Flash no permite acceso directo a archivos, solo subir. – Evert

7

Python Handler?

Uso de un controlador POST de Python en lugar de PHP. Genere un identificador único de su aplicación PHP que el cliente pueda colocar en los encabezados HTTP. Con mod_python para rechazar o aceptar la carga grande antes de que se transmita todo el cuerpo POST.

creo http://www.modpython.org/live/current/doc-html/dir-handlers-hph.html

Permite comprobar cabeceras y rechaza el resto de la entrada de la POST. No lo he intentado pero ¿podría ser el camino correcto?

Al observar el origen de mod_python, el almacenamiento en búfer de la entrada a través de read() parece permitir la evaluación bit a la vez de la entrada HTTP. Los encabezados son lo primero.

https://svn.apache.org/repos/asf/quetzalcoatl/mod_python/trunk/src/filterobject.c

+1

Parece la única solución real a la pregunta publicada hasta el momento. –

14

upload_max_filesize se puede ajustar on a per-directory basis; lo mismo vale para post_max_size

ej .:

<Directory /uploadpath/> 
    php_value upload_max_filesize 10G 
    php_value post_max_size 10G 
</IfModule> 
+6

¿Eso significa que realmente * necesita * 10G de RAM en el servidor o es solo una configuración para evitando cargar ataques/errores? –

+0

@MartinWickman aparentemente no de acuerdo con una prueba que hice. A menos que abras el archivo, por supuesto. Pude subir un archivo de 500MB, inc. 'move_uploaded_file' solo usando 0.2MB de acuerdo con' memory_get_usage (VERDADERO) ' – artfulrobot

+0

@artfulrobot' memory_get_usage' omite mucho; por ejemplo, si SELECCIONA un registro de datos de un databa por ejemplo, verás que el uso de tu memoria aumentará aproximadamente en un 'concierto', pero 'memory_get_usage' y el límite de memoria de PHP no contarán nada hasta que lo recuperes del recurso de la base de datos en variables PHP locales. Intentaría ver la utilización de la memoria de Apache en 'top' durante la carga, para estar seguro. –

1

que he tenido éxito con uploadify, y lo recomendaría. Es una secuencia de comandos jQuery/Flash que maneja grandes cargas, y puede pasarle parámetros adicionales (como la clave secreta). Para resolver los problemas del lado del servidor, simplemente use el siguiente código. Los cambios surtan efecto sólo para la secuencia de comandos que se llaman en:

//Check to see if the key is there 
if(!isset($_POST['secret_key']) || !isValid($_POST['secret_key'])) 
{ 
    exit("Invalid request"); 
} 
function isValid($key) 
{ 
    //Put your validation code here. 
} 

//This line changes the timeout. 
//Give it a value in seconds (3600 = 1 hour) 
set_time_limit(3600); 

//Set these amounts to whatever you need. 
ini_set("post_max_size","8192M"); 
ini_set("upload_max_filesize","8192M"); 

//Generally speaking, the memory_limit should be higher 
//than your post size. So make sure that's right too. 
ini_set("memory_limit","8200M"); 

EDITAR En respuesta a tu comentario:

Teniendo en cuenta lo que has dicho, me temo que no puede ser capaz para cumplir con sus requisitos a través de http. Todas las soluciones disponibles son códigos que agregan funciones a http para las que nunca se diseñaron.

Como dijo usted mismo, es un protocolo simple. Además de escribir su propio software de cliente que se ejecuta fuera del navegador, un applet de Java o usar un protocolo diferente (como FTP, que fue diseñado para esto), es posible que no obtenga lo que desea.

He hecho lo mejor que pude dentro de las limitaciones dadas. Lo siento, no pude hacerlo mejor.

+0

El flash no funciona bien, lea los comentarios anteriores. Establecer el upload_max_filesize y post_max_size después de que el script ya haya comenzado no tendrá ningún efecto. – Evert

2

Tome un vistazo a jumploader.com

Un buen java-applet para subir.

Lo he usado para subir imágenes y funciona bien. No he intentado con archivos más grandes que 10MB, pero también debería trabajar para archivos realmente grandes.

7

Es viejo, lo sé, pero tal vez alguien también tenga este problema hoy en día. Ahora puede hacer esto solo con Javascript y, por ejemplo, PHP. No se requiere Flash o Java en el lado del cliente.

demo: http://dnduploader.filkor.org/

La idea es cortar los archivos con una rodaja de Blob Javascript método() ...

-1

Prueba esto: http://www.simple2ftp.com utiliza un applet de Java FTP basado desde dentro de una envoltura de aplicación PHP inteligente.

+0

"HTTP es obligatorio" ... ¿Pero no está basado en FTP? –

Cuestiones relacionadas