मैं जल्दी से कनेक्शन कैसे बंद करूं?


99

मैं AJAX कॉल (JQuery के माध्यम से) करने की कोशिश कर रहा हूं जो काफी लंबी प्रक्रिया शुरू करेगा। मैं स्क्रिप्ट को केवल एक प्रतिक्रिया भेजने का संकेत देना चाहता हूं जो यह संकेत देता है कि प्रक्रिया शुरू हो गई है, लेकिन जब तक PHP स्क्रिप्ट चालू नहीं होती तब तक JQuery प्रतिक्रिया को वापस नहीं करेगा।

मैंने इसे "क्लोज़" हेडर (नीचे), और आउटपुट बफ़रिंग के साथ भी आज़माया है; न तो काम लगता है। कोई अंदाज़ा? या यह कुछ मुझे 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.' );

?>

क्या आपने ob_flush () के साथ अपने आउटपुट बफर को फ्लश किया और यह काम नहीं किया?
विंको वर्सालोविच

जवाबों:


87

निम्न PHP मैनुअल पेज (incl। उपयोगकर्ता-नोट्स) PHP स्क्रिप्ट को समाप्त किए बिना ब्राउज़र से टीसीपी कनेक्शन को बंद करने के बारे में कई निर्देश सुझाता है।

माना जाता है कि यह एक करीबी हेडर भेजने की तुलना में थोड़ा अधिक आवश्यक है।


ओपी फिर पुष्टि करता है: हाँ, यह चाल चली : उपयोगकर्ता-नोट # 71172 (नवंबर 2006) की ओर इशारा करते हुए यहां कॉपी की गई:

अपने PHP स्क्रिप्ट को चालू रखते हुए उपयोगकर्ता ब्राउज़र कनेक्शन को बंद करना [PHP] 4.1 के बाद से एक मुद्दा रहा है, जब व्यवहार register_shutdown_function() को संशोधित किया गया था ताकि यह स्वचालित रूप से उपयोगकर्ताओं के कनेक्शन को बंद न करे।

मेल डॉट xubion डॉट हू पर sts मूल समाधान पोस्ट:

<?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");
?>

जो तब तक ठीक काम करता है जब तक कि आप उसका विकल्प नहीं बनाते phpinfo()हैंecho('text I want user to see'); जिस स्थिति में हेडर कभी नहीं भेजा जाता है!

समाधान स्पष्ट रूप से आउटपुट बफ़रिंग को बंद करना है और अपनी हेडर जानकारी भेजने से पहले बफर को साफ़ करना है। उदाहरण:

<?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');
?>

यह पता लगाने की कोशिश में सिर्फ 3 घंटे खर्च हुए, आशा है कि यह किसी की मदद करता है :)

में परीक्षण किया गया:

  • IE 7.5730.11
  • मोज़िला फ़ायरफ़ॉक्स 1.81

बाद में जुलाई 2010 में एक संबंधित उत्तर में आर्कटिक फायर ने फिर दो और उपयोगकर्ता-नोट्स जोड़े जो ऊपर दिए गए थे:


7
हाँ, यह चाल चली
Eric_WVGG

1
लेखक और @ टिम्बो व्हाइट, क्या सामग्री के आकार को जाने बिना किसी कनेक्शन को जल्दी बंद करना संभव है? IE, बंद करने से पहले सामग्री पर कब्जा किए बिना।
स्काइबुलक

3
हैकर्स और गंदे वेब ब्राउज़र अभी भी कनेक्शन-बंद HTTP हेडर को अनदेखा कर सकते हैं, और बाकी आउटपुट प्राप्त कर सकते हैं .. सुनिश्चित करें कि आगे क्या आता है, संवेदनशील नहीं है। शायद एक obst (); सब कुछ को दबाने के लिए: p
hanshenrik

3
Fastcgi_finish_request () जोड़ना; जब ऊपर काम नहीं करता है तो कनेक्शन को सफलतापूर्वक बंद करने के लिए कहा गया है। हालांकि, मेरे मामले में इसने मेरी स्क्रिप्ट को जारी रखने से रोका, इसलिए सावधानी के साथ उपयोग करें।
एरिक दुबे

@ रीचर्डस्मिथ क्योंकि Connection: closeहेडर को स्टैक में अन्य सॉफ़्टवेयर द्वारा अधिलेखित किया जा सकता है, उदाहरण के लिए, सीजीआई के मामले में रिवर्स प्रॉक्सी (मैंने उस व्यवहार को नगीनेक्स के साथ देखा)। उस बारे में @hanshenrik से जवाब देखें। सामान्य तौर Connection: closeपर, क्लाइंट की ओर से निष्पादित किया जाता है, और इस प्रश्न के उत्तर के रूप में नहीं माना जाना चाहिए। कनेक्शन सर्वर की ओर से बंद होना चाहिए ।
7heo.tk

56

इन 2 हेडर को भेजना आवश्यक है:

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

जब से आपको अपने आउटपुट का आकार पता होना चाहिए, आपको अपने आउटपुट को बफर करने की आवश्यकता होगी, फिर इसे ब्राउज़र में फ्लश करें:

// 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 ********/

साथ ही, यदि आपका वेब सर्वर आउटपुट पर स्वचालित gzip कम्प्रेशन का उपयोग कर रहा है (यानी mod_deflate के साथ Apache), तो यह काम नहीं करेगा क्योंकि आउटपुट का वास्तविक आकार बदल गया है, और सामग्री-लंबाई अब सटीक नहीं है। विशेष स्क्रिप्ट को गज़िप संपीड़न अक्षम करें।

अधिक जानकारी के लिए, http://www.zulius.com/how-to/close-browser-connection-continue-exionion पर जाएँ


16
यदि आपका सर्वर आउटपुट को संपीड़ित करता है, तो आप इसे अक्षम कर सकते हैं header("Content-Encoding: none\r\n");जिस तरह से अपाचे इसे संपीड़ित नहीं करेगा।
GDmac

1
@GDmac धन्यवाद! मुझे यह थोड़ी देर के लिए काम करने के लिए नहीं मिला, लेकिन संपीड़न को अक्षम करने ने चाल चली।
रिएक्टगुलर

ob_flush()आवश्यक नहीं है और वास्तव में एक नोटिस का कारण बनता है failed to flush buffer। मैंने इसे निकाल लिया और इसने बहुत अच्छा काम किया।
लेवी

2
मैंने पाया है कि ob_flush()लाइन था आवश्यक।
डेबस्टर

21

आप fastcgi_end_request()फ़ंक्शन का उपयोग करने के लिए PHP-FPM के साथ फास्ट-सीजीआई का उपयोग कर सकते हैं । इस तरह, आप कुछ प्रसंस्करण करना जारी रख सकते हैं जबकि ग्राहक को प्रतिक्रिया पहले ही भेजी जा चुकी है।

आप इसे यहां PHP मैनुअल में पाते हैं: FastCGI प्रोसेस मैनेजर (FPM) ; लेकिन वह कार्य विशेष रूप से मैनुअल में आगे प्रलेखित नहीं है। यहां PHP-FPM: PHP FastCGI प्रोसेस मैनेजर विकी के अंश :


fastcgi_finish_request ()

स्कोप: php फ़ंक्शन

श्रेणी: अनुकूलन

यह सुविधा आपको कुछ php प्रश्नों के कार्यान्वयन में तेजी लाने की अनुमति देती है। त्वरण संभव है जब स्क्रिप्ट निष्पादन की प्रक्रिया में ऐसी क्रियाएं होती हैं जो सर्वर प्रतिक्रिया को प्रभावित नहीं करती हैं। उदाहरण के लिए, मेमेकेड में सत्र को सहेजना पृष्ठ के बनने और वेब सर्वर पर जाने के बाद हो सकता है।fastcgi_finish_request()एक php सुविधा है, जो प्रतिक्रिया आउटपुट को रोकती है। वेब सर्वर तुरंत क्लाइंट को "धीरे और दुख की बात" प्रतिक्रिया देना शुरू कर देता है, और एक ही समय में php क्वेरी के संदर्भ में कई उपयोगी चीजें कर सकता है, जैसे सत्र को सहेजना, डाउनलोड किए गए वीडियो को परिवर्तित करना, सभी प्रकार से निपटना सांख्यिकी के आदि।

fastcgi_finish_request() शटडाउन फ़ंक्शन को निष्पादित कर सकता है।


नोट: fastcgi_finish_request() है एक मोड़ जहां कॉल करने के लिए flush, printया echoजल्दी स्क्रिप्ट समाप्त कर देगा।

उस समस्या से बचने के लिए, आप कॉल के ignore_user_abort(true)ठीक पहले या बाद में fastcgi_finish_requestकॉल कर सकते हैं:

ignore_user_abort(true);
fastcgi_finish_request();

3
इस कार्रवाई ANSWER है!
किरिल टिटोव

2
अगर आप php-fpm का उपयोग कर रहे हैं - बस इस फ़ंक्शन का उपयोग करें - हेडर और बाकी सब के बारे में भूल जाएं। मुझे इतना समय बचाया!
रोस

17

पूर्ण संस्करण:

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();

किस अर्थ में पूरा हुआ? किस समस्या के लिए आपको स्वीकृत उत्तर स्क्रिप्ट को पूरा करने की आवश्यकता थी (कौन सा?) और आपके कौन से कॉन्फ़िगरेशन अंतर ने इसे आवश्यक बना दिया?
हक्रे

4
यह पंक्ति: शीर्ष लेख ("सामग्री-एन्कोडिंग: कोई नहीं"); -> बहुत महत्वपूर्ण है।
बॉबी टेबल्स

2
धन्यवाद, यह इस पृष्ठ पर एकमात्र कार्यशील समाधान है। इसे उत्तर के रूप में अनुमोदित किया जाना चाहिए।

6

एक बेहतर समाधान एक पृष्ठभूमि प्रक्रिया कांटा है। यह यूनिक्स / लिनक्स पर काफी सीधा है:

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

आपको बेहतर उदाहरणों के लिए इस प्रश्न को देखना चाहिए:

PHP एक पृष्ठभूमि प्रक्रिया को निष्पादित करता है


4

मान लें कि आपके पास एक लिनक्स सर्वर और रूट एक्सेस है, तो यह प्रयास करें। यह सबसे आसान उपाय है जो मैंने पाया है।

निम्न फ़ाइलों के लिए एक नई निर्देशिका बनाएं और इसे पूर्ण अनुमति दें। (हम इसे बाद में अधिक सुरक्षित बना सकते हैं।)

mkdir test
chmod -R 777 test
cd test

इसे एक फ़ाइल में रखें bgping

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

ध्यान दें &। पिंग कमांड बैकग्राउंड में चलेगी जबकि इको कमांड पर वर्तमान प्रक्रिया चलती है। यह www.google.com को 15 बार पिंग करेगा, जिसमें लगभग 15 सेकंड लगेंगे।

इसे अमल में लाएं।

chmod 777 bgping

इसे एक फ़ाइल में रखें 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";

?>

जब आप अपने ब्राउज़र में bgtest.php का अनुरोध करते हैं, तो आपको पिंग कमांड को पूरा करने के लिए लगभग 15 सेकंड इंतजार किए बिना, जल्दी से निम्नलिखित प्रतिक्रिया मिलनी चाहिए।

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

result:0
end bgtest.php

पिंग कमांड अब सर्वर पर चलना चाहिए। पिंग कमांड के बजाय, आप एक PHP स्क्रिप्ट चला सकते हैं:

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

उम्मीद है की यह मदद करेगा!


4

यहां टिम्बो के कोड में संशोधन किया गया है जो 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 ********/

आप एक भगवान हैं। मैं 2 दिनों के लिए काम कर रहा हूँ और यह पता लगाने के लिए। यह मेरे स्थानीय देव पर काम करता है लेकिन मेजबान पर नहीं। मुझे लगाया गया था। तुमने मुझे बचाया। धन्यवाद!!!!
चाड काल्डवेल

3

मैं एक साझा होस्ट पर हूँ और fastcgi_finish_request स्क्रिप्ट से पूरी तरह बाहर निकलने के लिए तैयार । मुझे connection: closeसमाधान पसंद नहीं है । इसके उपयोग से अतिरिक्त सर्वर संसाधनों की लागत के बाद के अनुरोधों के लिए एक अलग कनेक्शन होता है। मैंने Transfer-Encoding: cunked विकिपीडिया लेख पढ़ा और सीखा कि 0\r\n\r\nएक प्रतिक्रिया को समाप्त करता है। मैंने ब्राउज़रों के संस्करणों और उपकरणों में इसका पूरी तरह से परीक्षण नहीं किया है, लेकिन यह मेरे वर्तमान ब्राउज़र के सभी 4 पर काम करता है।

// 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);
}

आपके अच्छे उत्तर के लिए धन्यवाद, मुझे एहसास हुआ कि कनेक्शन का उपयोग करना कितना बेवकूफी (और अनावश्यक) है: करीब। मुझे लगता है कि कुछ अपने सर्वर के नट और बोल्ट से परिचित नहीं हैं।
जस्टिन

@ जस्टिन मैंने इसे बहुत पहले लिखा था। इसे फिर से देखते हुए, मुझे यह ध्यान देना चाहिए कि 4KB के लिए चंक्स को बाहर निकालना आवश्यक है। मुझे याद है कि कुछ सर्वर तब तक फ्लश नहीं करेंगे जब तक वे उस न्यूनतम तक नहीं पहुंच जाते।
skibulk

2

आप मल्टीथ्रेडिंग करने की कोशिश कर सकते हैं।

आप एक स्क्रिप्ट को व्हिप कर सकते हैं जो एक सिस्टम कॉल ( शेल_सेक्स का उपयोग करके) बनाता है ) करता है जो आपके काम को पैरामीटर के रूप में करने के लिए स्क्रिप्ट के साथ php बाइनरी को कॉल करता है। लेकिन मुझे नहीं लगता कि यह सबसे सुरक्षित तरीका है। हो सकता है कि आप php प्रक्रिया और अन्य सामान को काटकर सामान को ऊपर उठा सकते हैं

वैकल्पिक रूप से, phpclasses पर एक वर्ग है जो http://www.phpclasses.org/browse/package/b5353.html करता है । लेकिन मैं कार्यान्वयन की बारीकियों को नहीं जानता


और अगर आप प्रक्रिया को समाप्त करने के लिए इंतजार नहीं करना चाहते हैं, &तो पृष्ठभूमि में प्रक्रिया को चलाने के लिए चरित्र का उपयोग करें ।
लियाम

2

TL; DR उत्तर:

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.

उत्तर:

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

Php में कुछ समानांतर प्रोग्रामिंग करके आपकी समस्या को हल किया जा सकता है। मैंने कुछ हफ़्ते पहले इसके बारे में एक सवाल पूछा था: PHP अनुप्रयोगों में मल्टी थ्रेडिंग का उपयोग कैसे किया जा सकता है

और शानदार जवाब मिले। मुझे एक विशेष रूप से बहुत पसंद आया। लेखक का भी उल्लेख किया करने के लिए PHP में आराम से समानांतर प्रसंस्करण ट्यूटोरियल; (johnlim द्वारा सितं, 2008) , जो वास्तव में बहुत अच्छी तरह से अपनी समस्या को हल कर सकते हैं के रूप में मैं इसे इस्तेमाल किया है पहले से ही एक समान समस्या यह है कि पहले कुछ दिनों के लिए आया से निपटने के लिए।


1

जोएरी सेब्रेट्स का जवाब करीब है, लेकिन यह किसी भी मौजूदा सामग्री को नष्ट कर देता है जिसे डिस्कनेक्ट करने से पहले आप बफर कर सकते हैं। यह ignore_user_abortठीक से कॉल नहीं करता है, स्क्रिप्ट को समय से पहले समाप्त करने की अनुमति देता है। diyism का उत्तर अच्छा है, लेकिन से लागू नहीं है। उदाहरण के लिए, किसी व्यक्ति के पास अधिक या कम आउटपुट बफ़र्स हो सकते हैं, जो उत्तर नहीं देता है, इसलिए यह आपकी स्थिति में बस काम नहीं कर सकता है और आपको पता नहीं चलेगा कि क्यों।

यह फ़ंक्शन आपको किसी भी समय डिस्कनेक्ट करने की अनुमति देता है (जब तक हेडर अभी तक नहीं भेजे गए हैं) और आपके द्वारा अब तक उत्पन्न की गई सामग्री को बनाए रखता है। अतिरिक्त प्रसंस्करण समय डिफ़ॉल्ट रूप से असीमित है।

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();
}

यदि आपको अतिरिक्त मेमोरी की आवश्यकता है, तो भी, इस फ़ंक्शन को कॉल करने से पहले इसे आवंटित करें।


1

Mod_fcgid उपयोगकर्ताओं के लिए ध्यान दें (कृपया, अपने जोखिम पर उपयोग करें)।

त्वरित समाधान

जोएरी सेब्रेट्स का स्वीकृत उत्तर वास्तव में कार्यात्मक है। हालाँकि, यदि आप mod_fcgid का उपयोग करते हैं, तो आप पा सकते हैं कि यह समाधान अपने आप काम नहीं करता है। दूसरे शब्दों में, जब फ्लश फ़ंक्शन को कहा जाता है तो क्लाइंट का कनेक्शन बंद नहीं होता है।

FcgidOutputBufferSizeके विन्यास पैरामीटर mod_fcgid दोष करने के लिए हो सकता है। मुझे यह टिप मिली है:

  1. ट्रैवर्स कार्टर का यह उत्तर और
  2. Seumas Mackinnon की यह ब्लॉग पोस्ट

उपरोक्त पढ़ने के बाद, आप इस निष्कर्ष पर आ सकते हैं कि लाइन को जोड़ने के लिए एक त्वरित समाधान होगा (अंत में "उदाहरण वर्चुअल होस्ट देखें"):

FcgidOutputBufferSize 0

आपकी अपाचे कॉन्फ़िगरेशन फ़ाइल (जैसे, httpd.conf), आपकी FCGI कॉन्फ़िगरेशन फ़ाइल (जैसे, fcgid.conf) या आपकी वर्चुअल होस्ट फ़ाइल (जैसे, httpd-vhosts.conf) में।

ऊपर (1) में, "OutputBufferSize" नामक एक चर का उल्लेख किया गया है। यह FcgidOutputBufferSizeउल्लिखित (2) में पुराना नाम है ( mod_fcgid के लिए अपाचे वेब पेज में उन्नयन नोट देखें )।

विवरण और दूसरा समाधान

उपरोक्त समाधान mod_fcgid द्वारा निष्पादित बफरिंग को निष्क्रिय कर देता है या तो पूरे सर्वर के लिए या किसी विशिष्ट वर्चुअल होस्ट के लिए करता है। यह आपकी वेब साइट के लिए एक प्रदर्शन जुर्माना हो सकता है। दूसरी ओर, यह अच्छी तरह से मामला नहीं हो सकता है क्योंकि PHP अपने दम पर बफरिंग करता है।

यदि आप mod_fcgid की बफरिंग को अक्षम नहीं करना चाहते हैं तो एक और उपाय है ... आप इस बफर को फ्लश करने के लिए मजबूर कर सकते हैं

नीचे दिए गए कोड जोरी सेब्रेट्स द्वारा प्रस्तावित समाधान पर निर्माण करके ऐसा करते हैं:

<?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');
?>

कोड की अतिरिक्त पंक्ति अनिवार्य रूप से mod_fcgi के बफर को भरती है , इस प्रकार इसे फ्लश करने के लिए मजबूर करती है। संख्या "65537" को चुना गया क्योंकि FcgidOutputBufferSizeचर का डिफ़ॉल्ट मान "65536" है, जैसा कि संबंधित निर्देश के लिए अपाचे वेब पेज में उल्लेख किया गया है । इसलिए, यदि आपके वातावरण में कोई अन्य मान सेट है, तो आपको इस मान को समायोजित करने की आवश्यकता हो सकती है।

मेरा पर्यावरण

  • वैंपसर 2.5
  • अपाचे 2.4.9
  • PHP 5.5.19 VC11, x86, नॉन थ्रेड सेफ
  • mod_fcgid / 2.3.9
  • विंडोज 7 प्रोफेशनल x64

उदाहरण वर्चुअल होस्ट

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

    FcgidOutputBufferSize 0

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

मैंने कई उपाय आजमाए। और यह एकमात्र समाधान है जो मेरे लिए mod_fcgid के साथ काम कर रहा है।
Tsounabe

1

यह मेरे लिए काम किया

//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

ठीक है, तो मूल रूप से जिस तरह से jQuery XHR अनुरोध करता है, यहां तक ​​कि ob_flush विधि भी काम नहीं करेगी क्योंकि आप प्रत्येक onreadystatechange पर फ़ंक्शन चलाने में असमर्थ हैं। jQuery राज्य की जाँच करता है, फिर (पूर्ण, त्रुटि, सफलता, टाइमआउट) लेने के लिए उचित कार्यों का चयन करता है। और यद्यपि मुझे एक संदर्भ नहीं मिल पा रहा था, लेकिन मुझे याद है कि यह सब एक्सएचआर कार्यान्वयन के साथ काम नहीं करता है। एक विधि जो मेरा मानना ​​है कि आपके लिए काम करना चाहिए, ob_flush और हमेशा के लिए मतदान के बीच का अंतर है।

<?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>

और क्योंकि स्क्रिप्ट्स को इनलाइन निष्पादित किया जाता है, चूंकि बफ़र्स को फ्लश किया जाता है, इसलिए आपको निष्पादन मिलता है। इसे उपयोगी बनाने के लिए, डेटा प्राप्त करने और उस पर कार्य करने के लिए, मुख्य स्क्रिप्ट सेटअप में परिभाषित कॉलबैक विधि में कंसोल बदलें। उम्मीद है की यह मदद करेगा। चीयर्स, मॉर्गन।


0

एक वैकल्पिक उपाय यह है कि नौकरी को एक कतार में जोड़ा जाए और एक क्रोन स्क्रिप्ट बनाई जाए जो नई नौकरियों की जाँच करे और उन्हें चलाए।

मुझे ऐसा करना था कि हाल ही में एक साझा होस्ट द्वारा निष्पादित सीमाओं को दरकिनार करने के लिए - निष्पादन () एट अल वेबसर्वर द्वारा संचालित PHP के लिए अक्षम किया गया था, लेकिन एक शेल स्क्रिप्ट में चल सकता है।


0

यदि flush()कार्य नहीं करता है। आपको अगले विकल्प php.ini में सेट करने होंगे जैसे:

output_buffering = Off  
zlib.output_compression = Off  

0

नवीनतम कार्य समाधान

    // 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

इस धागे से कई अलग-अलग समाधानों की कोशिश करने के बाद (उनमें से किसी ने भी मेरे लिए काम नहीं किया), मैंने आधिकारिक PHP.net पेज पर समाधान ढूंढ लिया है:

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();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.