Làm cách nào để kết nối sớm?


99

Tôi đang cố thực hiện một cuộc gọi AJAX (thông qua JQuery) sẽ bắt đầu một quá trình khá dài. Tôi muốn tập lệnh chỉ gửi một phản hồi cho biết rằng quá trình đã bắt đầu, nhưng JQuery sẽ không trả lại phản hồi cho đến khi tập lệnh PHP chạy xong.

Tôi đã thử điều này với tiêu đề "đóng" (bên dưới) và cũng với bộ đệm đầu ra; dường như không hoạt động. Đoán nào? hay đây là điều tôi cần làm trong JQuery?

<?php

echo( "We'll email you as soon as this is done." );

header( "Connection: Close" );

// do some stuff that will take a while

mail( 'dude@thatplace.com', "okay I'm done", 'Yup, all done.' );

?>

bạn đã xóa bộ đệm đầu ra của mình bằng ob_flush () và nó không hoạt động?
Vinko Vrsalovic

Câu trả lời:


87

Trang hướng dẫn sử dụng PHP sau (bao gồm ghi chú người dùng) đề xuất nhiều hướng dẫn về cách đóng kết nối TCP với trình duyệt mà không cần kết thúc tập lệnh PHP:

Được cho là nó đòi hỏi nhiều hơn một chút so với việc gửi một tiêu đề đóng.


OP sau đó xác nhận: vâng, đây là mẹo: trỏ tới ghi chú người dùng # 71172 (tháng 11 năm 2006) được sao chép ở đây:

Việc đóng kết nối trình duyệt của người dùng trong khi vẫn giữ tập lệnh php của bạn chạy đã là một vấn đề kể từ [PHP] 4.1, khi hành vi của register_shutdown_function()được sửa đổi để nó không tự động đóng kết nối người dùng.

sts tại mail dot xubion dot hu Đã đăng lời giải gốc:

<?php
header("Connection: close");
ob_start();
phpinfo();
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();
flush();
sleep(13);
error_log("do something in the background");
?>

Điều nào hoạt động tốt cho đến khi bạn thay thế phpinfo()cho echo('text I want user to see');trường hợp đó các tiêu đề không bao giờ được gửi!

Giải pháp là tắt bộ đệm đầu ra một cách rõ ràng và xóa bộ đệm trước khi gửi thông tin tiêu đề của bạn. Thí dụ:

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();
echo('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here 
sleep(30);
echo('Text user will never see');
?>

Chỉ cần dành 3 giờ để tìm ra điều này, hy vọng nó sẽ giúp ích cho ai đó :)

Đã thử nghiệm trong:

  • IE 7.5730.11
  • Mozilla Firefox 1.81

Sau đó vào tháng 7 năm 2010 trong một câu trả lời có liên quan Arctic Fire sau đó đã liên kết hai ghi chú người dùng khác là phần tiếp theo với ghi chú ở trên:


7
yup, điều này đã làm các trick: php.net/manual/en/features.connection-handling.php#71172
Eric_WVGG

1
Tác giả và @Timbo White, Có thể đóng kết nối sớm mà không biết kích thước của nội dung không? IE, mà không cần phải nắm bắt nội dung trước khi đóng.
skibulk

3
Tin tặc và các trình duyệt web tồi vẫn có thể bỏ qua tiêu đề HTTP đóng kết nối và lấy phần còn lại của đầu ra .. hãy đảm bảo những gì xảy ra tiếp theo không nhạy cảm. có lẽ là ob_start (); để tất cả mọi thứ đàn áp: p
hanshenrik

3
Thêm fastcgi_finish_request (); đã được cho là đóng kết nối thành công khi cách trên không hoạt động. Tuy nhiên, trong trường hợp của tôi, nó ngăn tập lệnh của tôi tiếp tục thực thi, vì vậy hãy sử dụng một cách thận trọng.
Eric Dubé

@RichardSmith Vì Connection: closetiêu đề có thể bị phần mềm khác trong ngăn xếp ghi đè, ví dụ: proxy ngược trong trường hợp CGI (tôi đã quan sát thấy hành vi đó với nginx). Hãy xem câu trả lời từ @hanshenrik về điều đó. Nói chung, Connection: closeđược thực thi ở phía máy khách và không nên được coi là câu trả lời cho câu hỏi này. Kết nối phải được đóng từ phía máy chủ .
7heo.tk

56

Cần phải gửi 2 tiêu đề sau:

Connection: close
Content-Length: n (n = size of output in bytes )

Vì bạn cần biết kích thước đầu ra của mình, bạn sẽ cần đệm đầu ra của mình, sau đó chuyển nó vào trình duyệt:

// buffer all upcoming output
ob_start();
echo "We'll email you as soon as this is done.";

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/

Ngoài ra, nếu máy chủ web của bạn đang sử dụng tính năng nén gzip tự động trên đầu ra (ví dụ: Apache với mod_deflate), điều này sẽ không hoạt động vì kích thước thực của đầu ra đã thay đổi và Nội dung-Độ dài không còn chính xác. Tắt tính năng nén gzip của tập lệnh cụ thể.

Để biết thêm chi tiết, hãy truy cập http://www.zulius.com/how-to/close-browser-connection-continue-execution


16
Nếu máy chủ của bạn nén đầu ra, bạn có thể vô hiệu hóa nó bằng header("Content-Encoding: none\r\n");Cách đó apache sẽ không nén nó.
GDmac

1
@GDmac cảm ơn bạn! Tôi không thể làm cho điều này hoạt động trong một thời gian, nhưng vô hiệu hóa tính năng nén đã thực hiện thủ thuật.
Reactgular

Điều ob_flush()này là không cần thiết và thực sự gây ra một thông báo failed to flush buffer. Tôi đã lấy nó ra và điều này làm việc tuyệt vời.
Levi

2
Tôi thấy rằng ob_flush()dòng cần thiết.
Deebster

21

Bạn có thể sử dụng Fast-CGI với PHP-FPM để sử dụng fastcgi_end_request()chức năng . Bằng cách này, bạn có thể tiếp tục thực hiện một số xử lý trong khi phản hồi đã được gửi đến máy khách.

Bạn tìm thấy điều này trong hướng dẫn sử dụng PHP tại đây: FastCGI Process Manager (FPM) ; Nhưng chức năng đó cụ thể không được ghi thêm trong sách hướng dẫn. Đây là đoạn trích từ PHP-FPM: Wiki Trình quản lý quy trình PHP FastCGI :


fastcgi_finish_request ()

Phạm vi: hàm php

Thể loại: Tối ưu hóa

Tính năng này cho phép bạn tăng tốc độ thực hiện một số truy vấn php. Có thể tăng tốc khi có các hành động trong quá trình thực thi tập lệnh không ảnh hưởng đến phản hồi của máy chủ. Ví dụ: lưu phiên trong memcached có thể xảy ra sau khi trang đã được hình thành và chuyển đến máy chủ web. fastcgi_finish_request()là một tính năng php, dừng đầu ra phản hồi. Máy chủ web ngay lập tức bắt đầu chuyển phản hồi "chậm và đáng buồn" đến máy khách, đồng thời php có thể làm rất nhiều việc hữu ích trong ngữ cảnh của truy vấn, chẳng hạn như lưu phiên, chuyển đổi video đã tải xuống, xử lý tất cả các loại thống kê, v.v.

fastcgi_finish_request() có thể gọi hàm tắt đang thực thi.


Lưu ý: fastcgi_finish_request()một điều không minh bạch mà các cuộc gọi đến flush, printhoặc echosẽ chấm dứt kịch bản sớm.

Để tránh vấn đề đó, bạn có thể gọi ignore_user_abort(true)ngay trước hoặc sau fastcgi_finish_requestcuộc gọi:

ignore_user_abort(true);
fastcgi_finish_request();

3
ĐÂY LÀ CÂU TRẢ LỜI THỰC TẾ!
Kirill Titov

2
nếu bạn đang sử dụng php-fpm - chỉ cần sử dụng chức năng này - hãy quên tiêu đề và mọi thứ khác. Đã tiết kiệm cho tôi rất nhiều thời gian!
Ross

17

Phiên bản hoàn chỉnh:

ignore_user_abort(true);//avoid apache to kill the php running
ob_start();//start buffer output

echo "show something to user";
session_write_close();//close session file on server side to avoid blocking other requests

header("Content-Encoding: none");//send header to avoid the browser side to take content as gzip format
header("Content-Length: ".ob_get_length());//send length header
header("Connection: close");//or redirect to some url: header('Location: http://www.google.com');
ob_end_flush();flush();//really send content, can't change the order:1.ob buffer to normal buffer, 2.normal buffer to output

//continue do something on server side
ob_start();
sleep(5);//the user won't wait for the 5 seconds
echo 'for diyism';//user can't see this
file_put_contents('/tmp/process.log', ob_get_contents());
ob_end_clean();

hoàn thành theo nghĩa nào? Vấn đề nào đã yêu cầu bạn hoàn thành tập lệnh câu trả lời được chấp nhận (cái nào?) Và sự khác biệt nào về cấu hình của bạn khiến điều này trở nên cần thiết?
hakre

4
this line: header ("Content-Encoding: none"); -> rất quan trọng.
Bobby Tables

2
Cảm ơn, đây là giải pháp làm việc duy nhất trên trang này. Điều này nên được chấp thuận như là câu trả lời.

6

Một giải pháp tốt hơn là phân nhánh một quy trình nền. Nó khá thẳng về phía trước trên unix / linux:

<?php
echo "We'll email you as soon as this is done.";
system("php somestuff.php dude@thatplace.com >/dev/null &");
?>

Bạn nên xem câu hỏi này để biết các ví dụ tốt hơn:

PHP thực thi một quy trình nền


4

Giả sử bạn có máy chủ Linux và quyền truy cập root, hãy thử điều này. Đó là giải pháp đơn giản nhất mà tôi đã tìm thấy.

Tạo một thư mục mới cho các tệp sau và cấp cho nó đầy đủ quyền. (Chúng tôi có thể làm cho nó an toàn hơn sau này.)

mkdir test
chmod -R 777 test
cd test

Đặt cái này vào một tệp có tên bgping.

echo starting bgping
ping -c 15 www.google.com > dump.txt &
echo ending bgping

Lưu ý &. Lệnh ping sẽ chạy ở chế độ nền trong khi tiến trình hiện tại chuyển sang lệnh echo. Nó sẽ ping www.google.com 15 lần, quá trình này sẽ mất khoảng 15 giây.

Làm cho nó có thể thực thi được.

chmod 777 bgping

Đặt cái này vào một tệp có tên bgtest.php.

<?php

echo "start bgtest.php\n";
exec('./bgping', $output, $result)."\n";
echo "output:".print_r($output,true)."\n";
echo "result:".print_r($result,true)."\n";
echo "end bgtest.php\n";

?>

Khi bạn yêu cầu bgtest.php trong trình duyệt của mình, bạn sẽ nhanh chóng nhận được phản hồi sau, không cần đợi khoảng 15 giây để lệnh ping hoàn tất.

start bgtest.php
output:Array
(
    [0] => starting bgping
    [1] => ending bgping
)

result:0
end bgtest.php

Lệnh ping bây giờ sẽ chạy trên máy chủ. Thay vì lệnh ping, bạn có thể chạy một tập lệnh PHP:

php -n -f largejob.php > dump.txt &

Hi vọng điêu nay co ich!


4

Đây là một sửa đổi đối với mã của Timbo hoạt động với nén gzip.

// buffer all upcoming output
if(!ob_start("ob_gzhandler")){
    define('NO_GZ_BUFFER', true);
    ob_start();
}
echo "We'll email you as soon as this is done.";

//Flush here before getting content length if ob_gzhandler was used.
if(!defined('NO_GZ_BUFFER')){
    ob_end_flush();
}

// get the size of the output
$size = ob_get_length();

// send headers to tell the browser to close the connection
header("Content-Length: $size");
header('Connection: close');

// flush all output
ob_end_flush();
ob_flush();
flush();

// if you're using sessions, this prevents subsequent requests
// from hanging while the background process executes
if (session_id()) session_write_close();

/******** background process starts here ********/

BẠN LÀ THIÊN CHÚA. Tôi đã làm việc trong 2 ngày để thử và tìm ra điều này. Nó hoạt động trên nhà phát triển cục bộ của tôi nhưng không hoạt động trên máy chủ. Tôi đã được săn. BẠN ĐÃ CỨU TÔI. CẢM ƠN BẠN!!!!
Chad Caldwell

3

Tôi đang sử dụng máy chủ chia sẻ và fastcgi_finish_requestđược thiết lập để thoát hoàn toàn các tập lệnh. Tôi cũng không thích connection: closegiải pháp này. Sử dụng nó buộc một kết nối riêng biệt cho các yêu cầu tiếp theo, tốn thêm tài nguyên máy chủ. Tôi đã đọc Bài viết trên Transfer-Encoding: cunked Wikipedia và biết rằng điều đó sẽ 0\r\n\r\nchấm dứt phản hồi. Tôi chưa kiểm tra kỹ tính năng này trên các phiên bản trình duyệt và thiết bị, nhưng nó hoạt động trên cả 4 trình duyệt hiện tại của tôi.

// Disable automatic compression
// @ini_set('zlib.output_compression', 'Off');
// @ini_set('output_buffering', 'Off');
// @ini_set('output_handler', '');
// @apache_setenv('no-gzip', 1);

// Chunked Transfer-Encoding & Gzip Content-Encoding
function ob_chunked_gzhandler($buffer, $phase) {
    if (!headers_sent()) header('Transfer-Encoding: chunked');
    $buffer = ob_gzhandler($buffer, $phase);
    return dechex(strlen($buffer))."\r\n$buffer\r\n";
}

ob_start('ob_chunked_gzhandler');

// First Chunk
echo "Hello World";
ob_flush();

// Second Chunk
echo ", Grand World";
ob_flush();

ob_end_clean();

// Terminating Chunk
echo "\x30\r\n\r\n";
ob_flush();
flush();

// Post Processing should not be displayed
for($i=0; $i<10; $i++) {
    print("Post-Processing");
    sleep(1);
}

Nhờ câu trả lời hay của bạn, tôi đã nhận ra rằng việc sử dụng kết nối: close là ngu ngốc như thế nào (và không cần thiết). Tôi đoán một số không quen thuộc với các đai ốc và bu lông của máy chủ của họ.
Justin

@Justin Tôi đã viết bài này lâu rồi. Nhìn lại nó, tôi nên lưu ý rằng có thể cần phải nâng các khối lên 4KB. Tôi dường như nhớ rằng một số máy chủ sẽ không hoạt động cho đến khi chúng đạt đến mức tối thiểu đó.
skibulk

2

Bạn có thể thử thực hiện đa luồng.

bạn có thể tạo ra một tập lệnh thực hiện lệnh gọi hệ thống (sử dụng shell_exec ) gọi mã nhị phân php với tập lệnh để thực hiện công việc của bạn dưới dạng tham số. Nhưng tôi không nghĩ đó là cách an toàn nhất. Có thể bạn có thể làm chặt chẽ hơn bằng cách khởi động quá trình php và những thứ khác

Ngoài ra, có một lớp tại phpclasses làm điều đó http://www.phpclasses.org/browse/package/3953.html . Nhưng tôi không biết chi tiết cụ thể của việc triển khai


Và nếu bạn không muốn đợi quá trình kết thúc, hãy sử dụng &ký tự để chạy quá trình trong nền.
Liam

2

TL; DR Trả lời:

ignore_user_abort(true); //Safety measure so that the user doesn't stop the script too early.

$content = 'Hello World!'; //The content that will be sent to the browser.

header('Content-Length: ' . strlen($content)); //The browser will close the connection when the size of the content reaches "Content-Length", in this case, immediately.

ob_start(); //Content past this point...

echo $content;

//...will be sent to the browser (the output buffer gets flushed) when this code executes.
ob_end_flush();
ob_flush();
flush();

if(session_id())
{
    session_write_close(); //Closes writing to the output buffer.
}

//Anything past this point will be ran without involving the browser.

Câu trả lời chức năng:

ignore_user_abort(true);

function sendAndAbort($content)
{
    header('Content-Length: ' . strlen($content));

    ob_start();

    echo $content;

    ob_end_flush();
    ob_flush();
    flush();
}

sendAndAbort('Hello World!');

//Anything past this point will be ran without involving the browser.

1

Vấn đề của bạn có thể được giải quyết bằng cách thực hiện một số lập trình song song trong php. Tôi đã hỏi một câu hỏi về nó một vài tuần trước đây: Làm cách nào để sử dụng đa luồng trong các ứng dụng PHP

Và nhận được câu trả lời tuyệt vời. Tôi thích một đặc biệt rất nhiều. Nhà văn làm một tham chiếu đến chế biến song song dễ dàng trong PHP (tháng 9 năm 2008; bởi johnlim) hướng dẫn mà thực sự có thể giải quyết vấn đề của bạn rất tốt như tôi đã sử dụng nó đã để đối phó với một vấn đề tương tự mà đã đưa ra một vài ngày trước đây.


1

Câu trả lời của Joeri Sebrechts gần đúng, nhưng nó sẽ phá hủy mọi nội dung hiện có có thể được lưu vào bộ đệm trước khi bạn muốn ngắt kết nối. Nó không gọi ignore_user_abortđúng cách, cho phép tập lệnh kết thúc sớm. câu trả lời của diyism là tốt nhưng không thể áp dụng chung. Ví dụ: một người có thể có bộ đệm đầu ra lớn hơn hoặc ít hơn mà câu trả lời đó không xử lý được, vì vậy nó có thể không hoạt động trong tình huống của bạn và bạn sẽ không biết tại sao.

Chức năng này cho phép bạn ngắt kết nối bất kỳ lúc nào (miễn là tiêu đề chưa được gửi đi) và giữ lại nội dung bạn đã tạo cho đến nay. Theo mặc định, thời gian xử lý bổ sung là không giới hạn.

function disconnect_continue_processing($time_limit = null) {
    ignore_user_abort(true);
    session_write_close();
    set_time_limit((int) $time_limit);//defaults to no limit
    while (ob_get_level() > 1) {//only keep the last buffer if nested
        ob_end_flush();
    }
    $last_buffer = ob_get_level();
    $length = $last_buffer ? ob_get_length() : 0;
    header("Content-Length: $length");
    header('Connection: close');
    if ($last_buffer) {
        ob_end_flush();
    }
    flush();
}

Nếu bạn cũng cần thêm bộ nhớ, hãy cấp phát nó trước khi gọi hàm này.


1

Lưu ý cho người dùng mod_fcgid (vui lòng tự chịu rủi ro khi sử dụng).

Giải pháp nhanh

Câu trả lời được chấp nhận của Joeri Sebrechts thực sự là chức năng. Tuy nhiên, nếu bạn sử dụng mod_fcgid, bạn có thể thấy rằng giải pháp này không tự hoạt động. Nói cách khác, khi chức năng tuôn ra được gọi là kết nối với máy khách không bị đóng.

Các FcgidOutputBufferSizetham số cấu hình của mod_fcgid có thể đổ lỗi. Tôi đã tìm thấy mẹo này trong:

  1. câu trả lời này của Travers Carter
  2. bài đăng trên blog này của Seumas Mackinnon .

Sau khi đọc phần trên, bạn có thể đi đến kết luận rằng giải pháp nhanh chóng là thêm dòng (xem "Máy chủ ảo mẫu" ở cuối):

FcgidOutputBufferSize 0

trong tệp cấu hình Apache của bạn (ví dụ: httpd.conf), tệp cấu hình FCGI của bạn (ví dụ: fcgid.conf) hoặc trong tệp máy chủ ảo của bạn (ví dụ: httpd-vhosts.conf).

Trong (1) ở trên, một biến có tên "OutputBufferSize" được đề cập. Đây là tên cũ của tên FcgidOutputBufferSizeđược đề cập trong (2) (xem ghi chú nâng cấp trong trang web Apache cho mod_fcgid ).

Chi tiết & Giải pháp thứ hai

Giải pháp trên vô hiệu hóa bộ đệm được thực hiện bởi mod_fcgid cho toàn bộ máy chủ hoặc cho một máy chủ ảo cụ thể. Điều này có thể dẫn đến một hình phạt về hiệu suất cho trang web của bạn. Mặt khác, điều này có thể không đúng vì PHP tự thực hiện việc đệm.

Trong trường hợp bạn không muốn vô hiệu hóa bộ đệm của mod_fcgid , có một giải pháp khác ... bạn có thể buộc bộ đệm này xả .

Đoạn mã dưới đây thực hiện điều đó bằng cách xây dựng trên giải pháp do Joeri Sebrechts đề xuất:

<?php
    ob_end_clean();
    header("Connection: close");
    ignore_user_abort(true); // just to be safe
    ob_start();
    echo('Text the user will see');

    echo(str_repeat(' ', 65537)); // [+] Line added: Fill up mod_fcgi's buffer.

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush(); // Strange behaviour, will not work
    flush(); // Unless both are called !
    // Do processing here 
    sleep(30);
    echo('Text user will never see');
?>

Những gì dòng mã được thêm vào về cơ bản là lấp đầy bộ đệm của mod_fcgi , do đó buộc nó phải tuôn ra. Số "65537" được chọn vì giá trị mặc định của FcgidOutputBufferSizebiến là "65536", như đã đề cập trong trang web Apache cho chỉ thị tương ứng . Do đó, bạn có thể cần phải điều chỉnh giá trị này cho phù hợp nếu một giá trị khác được đặt trong môi trường của bạn.

Môi trường của tôi

  • WampServer 2.5
  • Apache 2.4.9
  • PHP 5.5.19 VC11, x86, Không an toàn cho luồng
  • mod_fcgid / 2.3.9
  • Windows 7 Professional x64

Máy chủ ảo mẫu

<VirtualHost *:80>
    DocumentRoot "d:/wamp/www/example"
    ServerName example.local

    FcgidOutputBufferSize 0

    <Directory "d:/wamp/www/example">
        Require all granted
    </Directory>
</VirtualHost>

Tôi đã thử nhiều giải pháp. Và đây là giải pháp duy nhất phù hợp với tôi với mod_fcgid.
Tsounabe

1

điều này làm việc cho tôi

//avoid apache to kill the php running
ignore_user_abort(true);
//start buffer output
ob_start();

echo "show something to user1";
//close session file on server side to avoid blocking other requests
session_write_close();

//send length header
header("Content-Length: ".ob_get_length());
header("Connection: close");
//really send content, can't change the order:
//1.ob buffer to normal buffer,
//2.normal buffer to output
ob_end_flush();
flush();
//continue do something on server side
ob_start();
//replace it with the background task
sleep(20);

0

Về cơ bản thì cách jQuery thực hiện yêu cầu XHR, ngay cả phương thức ob_flush cũng sẽ không hoạt động vì bạn không thể chạy một hàm trên mỗi onreadystatechange. jQuery kiểm tra trạng thái, sau đó chọn các hành động thích hợp để thực hiện (hoàn thành, lỗi, thành công, thời gian chờ). Và mặc dù tôi không thể tìm thấy tài liệu tham khảo, tôi nhớ lại rằng điều này không hoạt động với tất cả các triển khai XHR. Một phương pháp mà tôi tin rằng sẽ phù hợp với bạn là kết hợp giữa cuộc thăm dò ob_flush và forever-frame.

<?php
 function wrap($str)
 {
  return "<script>{$str}</script>";
 };

 ob_start(); // begin buffering output
 echo wrap("console.log('test1');");
 ob_flush(); // push current buffer
 flush(); // this flush actually pushed to the browser
 $t = time();
 while($t > (time() - 3)) {} // wait 3 seconds
 echo wrap("console.log('test2');");
?>

<html>
 <body>
  <iframe src="ob.php"></iframe>
 </body>
</html>

Và bởi vì các tập lệnh được thực thi nội tuyến, khi các bộ đệm được xóa, bạn sẽ được thực thi. Để làm cho điều này hữu ích, hãy thay đổi console.log thành một phương thức gọi lại được xác định trong thiết lập tập lệnh chính của bạn để nhận dữ liệu và hành động trên đó. Hi vọng điêu nay co ich. Chúc mừng, Morgan.


0

Một giải pháp thay thế là thêm công việc vào hàng đợi và tạo một tập lệnh cron để kiểm tra các công việc mới và chạy chúng.

Tôi đã phải làm theo cách đó gần đây để vượt qua các giới hạn do máy chủ chia sẻ áp đặt - executive () et al đã bị vô hiệu hóa đối với PHP do máy chủ web chạy nhưng có thể chạy trong tập lệnh shell.


0

Nếu flush()chức năng không hoạt động. Bạn phải đặt các tùy chọn tiếp theo trong php.ini như:

output_buffering = Off  
zlib.output_compression = Off  

0

Giải pháp làm việc mới nhất

    // client can see outputs if any
    ignore_user_abort(true);
    ob_start();
    echo "success";
    $buffer_size = ob_get_length();
    session_write_close();
    header("Content-Encoding: none");
    header("Content-Length: $buffer_size");
    header("Connection: close");
    ob_end_flush();
    ob_flush();
    flush();

    sleep(2);
    ob_start();
    // client cannot see the result of code below

0

Sau khi thử nhiều giải pháp khác nhau từ chuỗi này (sau khi không có giải pháp nào phù hợp với tôi), tôi đã tìm thấy giải pháp trên trang PHP.net chính thức:

function sendResponse($response) {
    ob_end_clean();
    header("Connection: close\r\n");
    header("Content-Encoding: none\r\n");
    ignore_user_abort(true);
    ob_start();

    echo $response; // Actual response that will be sent to the user

    $size = ob_get_length();
    header("Content-Length: $size");
    ob_end_flush();
    flush();
    if (ob_get_contents()) {
        ob_end_clean();
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.