2009-09-17 12 views
6

ja najpierw skonfigurować mój skrypt do uruchomienia nawet po żądania HTTP jest ponadCzy skrypt PHP może przekonać przeglądarkę do myślenia, że ​​żądanie HTTP zostało zakończone?

ignore_user_abort(true); 

następnie wypłukać jakiś tekst.

echo "Thats all folks!"; 
flush(); 

Jak mogę przekonać przeglądarkę do myślenia o zakończeniu żądania HTTP? dzięki temu mogę kontynuować pracę bez przeglądarki wyświetlającej "ładowanie strony".

header(??) // something like this? 

Odpowiedz

10

Oto jak to zrobić. Powiesz przeglądarce, aby przeczytała pierwsze N ​​znaków wyjściowych, a następnie zamknij połączenie, podczas gdy twój skrypt będzie działał, dopóki nie zostanie ukończony.

<?php 
ob_end_clean(); 
header("Connection: close"); 
ignore_user_abort(true); // optional 
ob_start(); 
echo ('Text the user will see'); 
$size = ob_get_length(); 
header("Content-Length: $size"); 
ob_end_flush();  // Will not work 
flush();   // Unless both are called ! 

// At this point, the browser has closed connection to the web server 

// Do processing here 
echo('Text user will never see'); 
?> 
+0

+1 Wspaniałe rozwiązanie! Dzięki za mądrość, której nie potrafili rozgryźć wszyscy jeźdźcy króla. –

+0

Naprawdę fajny hak autorstwa Milana. Ale muszę się zastanawiać, co robisz, co wymaga przeżycia procesu serwera sieciowego po zakończeniu żądania webowego (z perspektywy klienta). Oczywiście mam nadzieję, że ta obrzydliwość nie zostanie tak bardzo skalowana! – timdev

+3

Identyczne (do litery) do kodu na stronie podręcznika php powiązanego z odpowiedzią Lukmana, która została opublikowana dwa dni wcześniej. – GZipp

4

Nagłówki nie zadziała (są nagłówki, więc oni przychodzą pierwszy)

ja nie znam żadnego sposobu, aby zakończyć połączenie http bez zakończenia skryptu, choć przypuszczam jest jakiś niejasny sposób robienia tego.

Poinformowanie nas, co chcesz zrobić po złożeniu wniosku, pomoże nam przedstawić lepsze sugestie.

Ale ogólnie, będę myśleć o jedną z następujących czynności:

1) Wykonaj jakiś prosty skrypt wiersza polecenia (przy użyciu exec()), która wygląda następująco:

#!/bin/sh 
php myscript.php <arg1> <arg2> .. <argN> & 

następnie zaczynał że się ze skryptu http związany jak:

<?PHP 
exec('/path/to/my/script.sh'); 
?> 

Lub:

2) Napisz anothe r program (prawdopodobnie ciągle działający demon lub tylko jakiś skrypt, który jest tak często używany) i sprawdź, w jaki sposób twój kod może przekazać mu instrukcje. Możesz mieć tabelę bazy danych, która działa w kolejce, lub spróbować, aby działała z płaskim plikiem jakiegoś rodzaju. Możesz również użyć skryptu sieciowego, wywołując komendę z wiersza polecenia, która spowoduje, że twój skrypt nieoczekiwany będzie kolejkowany do pracy.

Pod koniec dnia użytkownik nie musi chcieć, aby skrypt był wykonywany po żądaniu http. Zakładając, że używasz mod_php, oznacza to, że będziesz wiązał proces apache, dopóki skrypt się nie zakończy.

+1

+1 Uzgodniono. Kontynuacja wykonywania po żądaniu WWW byłaby złym wyborem projektu i spowodowałaby niepotrzebne obciążenie pamięci na serwerze. – Fragsworth

+0

Wielki czas uzgodniony z Timem. Cały problem polega na tym, że chcesz zaoszczędzić kawałek pracy na później, a nie czekać. Cóż, po prostu łączysz zasoby httpd, które mogą blokować innych użytkowników. Pozwól, aby httpd obsługiwał klientów sieciowych i przekazywał inne prace do innego komponentu - demona (+1 na czas rzeczywisty), zaplanowanego zadania (+1 do grupowania i kolejkowania przetwarzania eratów, które NAPRAWDĘ może czekać) lub cokolwiek innego. –

2

Teoretycznie, jeśli protokół HTTP 1.1 keep-alive jest włączony, a klient otrzymuje liczbę znaków, których oczekuje od serwera, powinien traktować go jako koniec odpowiedzi i kontynuować renderowanie strony (przy zachowaniu połączenia . nadal otwarta) Spróbuj wysłać te nagłówki (jeśli nie można włączyć do nich w inny sposób):

 
Connection: keep-alive 
Content-Length: n 

Gdzie n to ilość znaków, które zostały wysłane w organizmie reagowania (buforowanie wyjścia może pomóc liczyć to.) Przykro mi, że nie mam czasu, aby sam to przetestować. Po prostu wrzucam sugestię na wypadek, gdyby to zadziałało.

+0

Nadal jest to zły pomysł, tak jakby przetwarzanie post-request trwało dłużej niż kilka ms (w takim przypadku, dlaczego pośpiech, aby zakończyć połączenie), lepiej jest zwolnić proces serwera WWW, aby obsłużyć nowe żądania i mieć trochę proces back-end (nie związany z httpd) przejmuje. – timdev

+0

Zgadzam się, że to prawdopodobnie zły pomysł. To tylko próba spełnienia wymagań PO. –

2

Najlepszym sposobem osiągnięcia tego celu jest za pomocą buforowania wyjścia. PHP wysyła nagłówki, gdy są dobre i gotowe, ale jeśli otoczysz wyjście do przeglądarki przez ob_ *, możesz kontrolować nagłówki na każdym kroku.

Możesz trzymać renderowaną stronę w buforze, jeśli chcesz i wysyłać nagłówki, dopóki słońce nie pojawi się w Chinach. Ta praktyka powoduje, że możesz zobaczyć wiele otwierających tagów <?php, ale nie ma w tej chwili tagów zamykających. Dzięki temu skrypt nie będzie wysyłać żadnych nagłówków przedwcześnie, ponieważ niektóre elementy mogą zostać uwzględnione.