2012-01-23 3 views
6

PHP 스크립트의 출력 스트림을 닫을 수 있습니까? 몇 가지 사후 처리를해야하는 스크립트가 있지만 사후 처리 도중 및 이후에 더 이상 클라이언트에 데이터를 보내지 않으므로 사후 처리 전에 연결을 닫고 싶습니다.PHP : 닫기 출력 스트림

편집 : 내 응용 프로그램에서 나는 지금 당장 다시 작성해야하는 캐시가 있습니다. 그러나 나는 사용자를 느리게하고 싶지 않다. 내가 원하는 것은 스크립트의 끝에서 캐시를 재 구축해야하는지 결정하는 것입니다. 따라서 출력 스트림을 먼저 닫고 사용자가 데이터를 얻은 다음 캐시를 다시 작성하려고합니다. 이 작업을 수행하는 것은 대단히 중요하지 않지만 먼저 연결을 종료하는 것이 더 바람직하다고 생각하므로 사용자는 캐시가 오래 걸리면 다시 작성된다는 사실을 알 수 없습니다.

+0

왜 이렇게해야합니까? 조금 더 이해할 수 있도록 약간의 코드를 게시 할 수 있습니까? –

+0

+1 조나단이 말한 것. 왜 당신이 이것을하고 싶은지 조금 더 말해주세요. –

답변

4

업데이트

이러한 경우를 처리하는 방법은 출력 버퍼링 및 해당 HTTP 헤더의 조합이다. HTTP/1.1 Specification Section 14.10에서

:

HTTP/1.1 연결이 반응 완료 후 폐쇄됩니다 신호를 보낸 사람에 대한 "close"연결 선택 사항을 정의한다. 우리는 HTTP 콘텐츠 길이 연결에 추가 헤더를 전달할 경우

그래서 : 지정된 응답 길이를 수신 한 후 가까운은 브라우저가 연결을 닫습니다 알고 :

  1. 전체 출력 데이터를 얻은 후에 클라이언트에 적절한 헤더를 보내십시오.
  2. 계속 하시겠습니까? r processing ...하지만 출력을 보내려고하지 않거나 헤더가 전송되었으므로 오류가 발생합니다.

너무 많은 처리를 수행하면 웹 서버 SAPI에서 스크립트 실행 시간 제한에 맞춰 실행할 수 있으므로주의하십시오. 마지막으로, ignore_user_abort()을 사용하여이 특정 스크립트에서 "사용자 중단"을 무시하도록 PHP에 지시해야합니다. 브라우저가 수행중인 작업의 결과로 연결을 닫고 PHP가 처리를 계속하기를 원하기 때문입니다.

<?php 
ignore_user_abort(); 
ob_start(); 

// do stuff, generate output 

// get size of the content 
$length = ob_get_length(); 

// tell client to close the connection after $length bytes received 
header('Connection: close'); 
header("Content-Length: $length"); 

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

// close session if you have one ... 
// continue your processing tasks ... 
?> 

당신은 Connection handlingdocs에 PHP 매뉴얼 섹션을 검사 할 수 있습니다.

출력 버퍼링을 시작하지 않으시겠습니까? 그런 다음 전송할 모든 출력을 캡처 한 다음 나중에 실제로 원하는 작업을 결정할 수 있습니다.

<?php 

echo 'before output buffering'; 
ob_start(); 
echo 'after output buffering'; 
$output = ob_get_contents(); 

// script's only output to this point will be 'before output buffering' 

// I changed my mind, send the output ... 
ob_end_flush(); 
?> 
+0

출력 버퍼링은 브라우저에 대한 출력 스트림을 계속 열어 둡니다. 몇 초가 걸리는 후 처리가 필요하다고 가정하면 브라우저는 후 처리가 완료 될 때까지 기다릴 것입니다. 특히 AJAX를 사용하면 웹 응용 프로그램이 많이 느려질 것입니다. 따라서 브라우저와의 연결을 닫을 수 있도록 브라우저가 출력을 처리 한 다음 사후 처리를 계속할 수 있어야합니다. – Tiddo

+0

@Tiddo 나는 정확한 해결책으로 나의 대답을 업데이트했다. – rdlowrey

+0

그건 아주 좋은 해결책입니다! 나는 그것을 잠시 후에 시험 할 것이다. 편집 : 그것은 위대한 작품! 고마워요! – Tiddo

0

나는 의견을 충분한 명성을 가지고,하지만 난 문제가 될 수있는 @rdlowrey 응답 gzip으로에 그것을 공유하고자합니다.당신이있는 경우

gzip을는 따라서는 콘텐츠 길이 헤더를 전송하지 않습니다 header("Transfer-encoding: none"); 그것을 변경하려고해도, 청크 헤더가 항상 로 설정되어 전송 인코딩을 사용 가능. 나는이 문제를 해결할 수

방법은 사용 된 다음 이전 : 다음

<? 
@ini_set('zlib.output_compression', 'Off'); 
@ini_set('output_buffering', 'Off'); 
@ini_set('output_handler', ''); 
@apache_setenv('no-gzip', 1); 
?> 

그리고 해결책 :

<? 
ignore_user_abort(); 
ob_start(); 

// do stuff, generate output 

// get size of the content 
$length = ob_get_length(); 

// tell client to close the connection after $length bytes received 
header('Connection: close'); 
header("Content-Length: $length"); 

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

// close session if you have one ... 
// continue your processing tasks ... 
?>