2009-09-26 12 views

Respuesta

2

Genera un proceso en segundo plano y devuelve una identificación de proceso en segundo plano para que el usuario pueda verificarlo más adelante a través de una URL secreta.

16

La directiva ignore_user_abort y la función ignore_user_abort son probablemente lo que está buscando: debería permitirle enviar la respuesta al navegador y, a continuación, ejecutar algunos cálculos en su servidor.

Este artículo le puede interesar: Cómo utilizar ignore_user_abort() para Procesar fuera de banda; citar:
EDITAR 2010-03-22: eliminado el enlace (se apunta a http:// ! waynepan.com/2007/10/11/ ! how-to-use-ignore_user_abort-to-do-process-out-of-band/ - eliminar los espacios y ! si quieres probar), después de ver el comentario de @ Joel.

Básicamente, cuando se utiliza ignore_user_abort(true) en su php script, éste continuará funcionando incluso si el usuario pulsa el esc o parar en su navegador. ¿Cómo se puede usar esto?
Un uso sería devolver contenido al usuario y permitir que la conexión se cierre mientras que procesar elementos que no requieren interacción del usuario.

el ejemplo siguiente se envía $response al usuario, cerrar la conexión (haciendo spinner/carga de tope de la barra del navegador), y luego ejecuta do_function_that_takes_five_mins();

Y el ejemplo dado:

ignore_user_abort(true); 
header("Connection: close"); 
header("Content-Length: " . mb_strlen($response)); 
echo $response; 
flush(); 
do_function_that_takes_five_mins(); 

(Hay más no copié y pego)


Tenga en cuenta que su script PHP todavía tiene que caber en los max_execution_time y limitaciones memory_limit - lo que significa que no debe utilizar esto para manipulaciones que tienen demasiado tiempo.

Esto también utilizará un proceso Apache, lo que significa que no debe tener docenas de páginas que lo hagan al mismo tiempo.

Aún así, buen truco para mejorar la experiencia de uso, supongo ;-)

+0

No funciona. Puede intentarlo para verlo: ignore_user_abort (true); header ('Content-Type: text/plain'); encabezado ("Conexión: cerrar"); echo 'algo'; sueño (20); exit(); Todavía demora 20 segundos en responder. – Mask

+0

El enlace a "Cómo usar ignore_user_abort() para hacer el procesamiento fuera de banda" contiene malware (cuando se lo ve a través de un referente, chupe como SO). Parece que el dueño del blog fue pirateado ... –

+0

@Joel: gracias por el comentario; He editado mi respuesta para eliminar el enlace ;; Acabo de dejar la URL, sin un hipervínculo, y con una advertencia –

-1

Usted necesita la llamada flush() tener la respuesta enviada al navegador de inmediato.

2

Más o menos depende de lo que está tratando de lograr.

En mi caso, tuve que hacer un montón de procesamiento del lado del servidor, con solo una cantidad mínima de datos que se envían de vuelta al navegador: resumen de información realmente.

Estaba tratando de crear un remitente de mensajes: envía un correo electrónico a más de 250 personas, pero posiblemente muchos más (depende de cuántos se hayan registrado en el sistema).

el controlador de correo PHP es rápido, pero para números grandes, no lo suficientemente rápido, por lo que estaba destinado a tiempo de espera. Para evitarlo, tuve que retrasar el tiempo de espera en el lado del servidor/PHP, y mantener el navegador pendiente hasta que todos los datos se hayan resumido y visualizado.

Mi solución: un adelanto.

esencialmente, le di al usuario un mensaje que decía algunas estadísticas iniciales (intentando enviar tantos correos electrónicos), creé 2 cuadros DIV (uno para información de estado actual, el segundo para información de resumen final), visualicé el pie de página, comencé el procesamiento, y cuando terminó, actualizó la información de resumen. va de la siguiente manera:

Comience recogiendo sus datos que va a procesar y obtenga información resumida. En mi caso, saqué la lista de direcciones de correo electrónico, las validé y las conté.

mostrará el "intento" Info:

echo "Message contents:"; 
echo "<blockquote>$msgsubject<p>$msgbody</blockquote><p>&nbsp;</p>"; 
echo "Attempting <strong>" . $num_rows . "</strong> email addresses."; 

Ahora crear algunas DIVs para el estado/información definitiva:

<div id=content name=content> 
<div id=progress name=progress style='border: black 1px solid; width: ".$boxwidth."px; height: 20px;'></div> 
<br> 
</div> 

donde $ boxwidth es el ancho que desea que su barra de progreso para ser (explicado más adelante)

Observe que están esencialmente vacíos, los llenaremos más tarde.

Por último, complete el resto de la página mostrando el pie de página (en mi caso, acabo de "incluir" el archivo correspondiente).

Ahora, todo eso todavía está colgando en el búfer de página, ya sea en el servidor (si PHP está almacenando en búfer) o en el navegador (porque aún no se ha dicho que hemos terminado), así que hagámoslo empujados y/o visualiza usando la opción "ignorar" y "flush" de arriba:

ignore_user_abort(true); 
flush(); 

Ahora que el navegador está empezando a mostrar las cosas, tenemos que dar al usuario algo que ver, así que aquí está la provocacion - crearemos una barra de estado que mostraremos en el DIV interno, y un mensaje final para el DIV externo.

tanto, como se bucle a través de sus datos, de forma periódica (Voy a dejar "con qué frecuencia" depende de usted para averiguar), la salida de los siguientes:

set_time_limit (3); 
... 
(process your data here) 
... 
<script>document.getElementById('progress').innerHTML += "<img src='images/progress_red.gif' width: $width height=20 border=0>"</script> 
flush(); 

Esto esencialmente apilar hasta el pequeño 4x20 progress_red imágenes una al lado de la otra, lo que hace que parezca que una barra roja se está moviendo a través de la pantalla. En mi caso, lo hice 100 veces, en base a un porcentaje de la cantidad que actualmente estaba procesando fuera del número total para procesar. El "set_time_limit" agregará 3 segundos al límite existente, para que sepa que su script no se ejecutará en el muro de límite de tiempo de PHP. Ajuste los 3 segundos para su aplicación según sea necesario.

aunque la página es técnicamente "completa", el código javascript actualizará el html DIV y nuestra barra de progreso se "moverá".

cuando todo hecho, i luego informar de cuántos artículos fueron realmente transformada y añadir que a la html DIV exterior y la página se completa:

<script>document.getElementById('content').innerHTML += "Message was sent to $sentcnt people."</script> 

El navegador está feliz porque ha tenido todos lo que es calificaciones cumplido (al final de la página sintactialmente), el usuario ve algo pasar hasta el final, y el servidor

Tiendo a no utilizar Javascript si puedo evitarlo, pero en el caso, no se realizaban cosas sofisticadas de CSS. a través del Javascript, por lo que es bastante sencillo y fácil ver qué sucede y poca sobrecarga en el sitio del navegador. Y funciona bastante bien.

No pretendo que sea perfecto, pero para una solución simple y de bajo costo, funciona para mí sin tener que crear cronjobs, mecanismos de puesta en cola adicionales o procesos secundarios.

Cuestiones relacionadas