prosource

PHP - Ajax로 데이터를 루프하는 동안 플러시

probook 2023. 8. 16. 22:27
반응형

PHP - Ajax로 데이터를 루프하는 동안 플러시

저는 PHP를 사용하여 큰 파일을 읽고 요청 시 현재 라인 번호를 전송하는 while 루프를 만들고 싶습니다.아약스를 이용해서 현재 라인 수를 받아서 페이지에 출력하고 싶습니다.는 html 버튼을 사용하여 ONCE만 실행하고 agax 메서드를 호출하는 Javascript 스레드를 클릭하여 활성화 또는 종료할 수 있었으면 합니다.

제가 시도해봤지만 어떤 이유에선지 제가 코멘트를 달지 않는 한 아무것도 인쇄되지 않습니다.echo str_repeat(' ',1024*64);함수를 사용하여 주석을 달면 전체 루프 결과가 표시됩니다.

1개 행 처리됨. 2개 행 처리됨. 3개 행 처리됨. 4개 행 처리됨. 5개 행 처리됨. 6개 행 처리됨. 7개 행 처리됨. 8개 행 처리됨. 9개 행 처리됨.10개의 행이 처리되었습니다.

다음과 같은 별도의 줄로 표시하는 대신 단일 줄로 표시:

1 row(s) processed.
2 row(s) processed.
3 row(s) processed.
4 row(s) processed.
5 row(s) processed.
6 row(s) processed.
7 row(s) processed.
8 row(s) processed.
9 row(s) processed.
10 row(s) processed.

또한 자바스크립트 스레드를 종료하는 방법을 잘 모르겠습니다.그래서 총 2개의 문제:

 1. It's returning the entire While loop object at once instead of each time it loops.
 2. I'm not sure how to terminate the JQuery thread.

아이디어 있어요?지금까지 제 코드는 아래와 같습니다.

msgserv.mss.messages

<?php

//Initiate Line Count
$lineCount = 0;

// Set current filename
$file = "test.txt";

// Open the file for reading
$handle = fopen($file, "r");

//Change Execution Time to 8 Hours
ini_set('max_execution_time', 28800);

// Loop through the file until you reach the last line
while (!feof($handle)) {

    // Read a line
    $line = fgets($handle);

    // Increment the counter
    $lineCount++;

    // Javascript for updating the progress bar and information
    echo $lineCount . " row(s) processed.";

    // This is for the buffer achieve the minimum size in order to flush data
    //echo str_repeat(' ',1024*64);

    // Send output to browser immediately
    flush();

    // Sleep one second so we can see the delay
    //usleep(100);
}

// Release the file for access
fclose($handle);

?>

AS.D.S.D.D.

<html>
    <head>
        <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript" charset="utf-8"></script>

        <style type="text/css" media="screen">
            .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
            .new{ background-color:#3B9957;}
            .error{ background-color:#992E36;}
        </style>

    </head>
    <body>

    <center>
        <fieldset>
            <legend>Count lines in a file</legend>
            <input type="button" value="Start Counting" id="startCounting" />
            <input type="button" value="Stop Counting!" onclick="clearInterval(not-Sure-How-To-Reference-Jquery-Thread);" />
        </fieldset>
    </center>

    <div id="messages">
        <div class="msg old"></div>
    </div>

    <script type="text/javascript" charset="utf-8">
        function addmsg(type, msg){
            /* Simple helper to add a div.
        type is the name of a CSS class (old/new/error).
        msg is the contents of the div */
            $("#messages").append(
            "<div class='msg "+ type +"'>"+ msg +"</div>"
        );
        }

        function waitForMsg(){
            /* This requests the url "msgsrv.php"
        When it complete (or errors)*/
            $.ajax({
                type: "GET",
                url: "msgsrv.php",
                async: true, /* If set to non-async, browser shows page as "Loading.."*/
                cache: false,
                timeout:2880000, /* Timeout in ms set to 8 hours */

                success: function(data){ /* called when request to barge.php completes */
                    addmsg("new", data); /* Add response to a .msg div (with the "new" class)*/
                    setTimeout(
                    'waitForMsg()', /* Request next message */
                    1000 /* ..after 1 seconds */
                );
                },
                error: function(XMLHttpRequest, textStatus, errorThrown){
                    addmsg("error", textStatus + " (" + errorThrown + ")");
                    setTimeout(
                    'waitForMsg()', /* Try again after.. */
                    "15000"); /* milliseconds (15seconds) */
                },
            });
        };

        $('#startCounting').click(function() {
            waitForMsg();
        });
    </script>

</body>
</html>

test.txt

1
2
3
4
5
6
7
8
9
10

당신은 PHP와 AJAX가 어떻게 상호작용하는지 혼란스럽습니다.

AJAX를 통해 PHP 페이지를 요청하면 PHP 스크립트 실행을 강제로 시작합니다.사용할 수도 있지만,flush()모든 내부 PHP 버퍼를 지우기 위해 AJAX 호출은 전체 파일을 읽을 때 발생하는 연결이 닫힐 때까지 종료되지 않습니다(즉, 응답 핸들러가 호출되지 않음).

원하는 것을 달성하려면 다음과 같은 병렬 프로세스 흐름이 필요합니다.

  1. 첫 번째 AJAX 게시물은 파일 읽기를 시작하라는 요청을 보냅니다.이 스크립트는 일부 대기열 ID를 생성하여 브라우저로 다시 보내고 실제로 파일 읽기를 수행하는 스레드를 생성한 다음 종료합니다.
  2. 이후의 모든 AJAX 요청은 파일 읽기 상태를 확인하는 다른 PHP 스크립트로 이동합니다.이 새로운 PHP 스크립트는 #1에서 생성된 고유 ID를 기반으로 파일 읽기의 현재 상태를 전송한 후 종료됩니다.

다음을 통해 프로세스 간 통신을 수행할 수 있습니다.$_SESSION데이터를 데이터베이스에 저장하는 방법을 사용할 수 있습니다.어느 쪽이든 현재 순차적인 구현 대신 병렬 구현이 필요합니다. 그렇지 않으면 전체 상태를 한 번에 계속 얻을 수 있습니다.

사용:

하나의 php 스레드에서 필요한 모든 것을 해야 합니다.

편집

nickb의 답변을 보십시오. 단순히 이를 수행하는 방법을 찾고 있다면 알고리즘을 따르는 것입니다.

  1. 는 Javascript를 엽니다.process.php 작업을하는 Ajax를가 연속 하는지 여부를 .
  2. 사용자가 새로 고침을 중지하기로 결정하면 제공된 링크에 표시된 대로 로드가 중지됩니다.

process.php:

ignore_user_abort(); // Script will finish in background
while(...){
  echo "Page: $i\n";
  ob_flush();
}

EDIT 2 요청된 예(조금 다르고 추하지만 단순함).test_process.php:

// This script will write numbers from 1 to 100 into file (whatever happens)
// And sends continuously info to user
$fp = fopen( '/tmp/output.txt', 'w') or die('Failed to open');
set_time_limit( 120);
ignore_user_abort(true);

for( $i = 0; $i < 100; $i++){
    echo "<script type=\"text/javascript\">parent.document.getElementById( 'foo').innerHTML += 'Line $i<br />';</script>";
    echo str_repeat( ' ', 2048);
    flush();
    ob_flush();
    sleep(1);
    fwrite( $fp, "$i\n");
}

fclose( $fp);

주요 html 페이지:

<iframe id="loadarea"></iframe><br />
<script>
function helper() {
    document.getElementById('loadarea').src = 'test_process.php';
}
function kill() {
    document.getElementById('loadarea').src = '';
}
</script>

<input type="button" onclick="helper()" value="Start">
<input type="button" onclick="kill()" value="Stop">
<div id="foo"></div>

시작 라인을 다음과 같이 누른 후:

Line 1
Line 2

에 했습니다.#foo가 내가 때칠을 때.Stop그들은 나타나지 않았지만 스크립트는 백그라운드에서 끝냈고 100개의 모든 숫자를 파일로 썼습니다.

, 면치를 치면,Start다시 스크립트는 구걸(실행 파일)에서 실행되기 시작하고 병렬 요청도 실행합니다.

http 스트리밍에 대한 자세한 내용은 이 링크를 참조하십시오.

더 간단한 솔루션은 기본(vanila js) XHR 개체를 사용해야 합니다.

아주 정교한 해결책이 있습니다, 긴 여론 조사에 대한 것입니다.

PHP:

<?php
header('Content-Type: text/html; charset=UTF-8');
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
  echo "<br> Line to show.";
  echo str_pad('',4096)."\n";
  ob_flush();
  flush();
  sleep(2);
}
echo "Done.";
ob_end_flush();

JS:

var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/some_service.php', true);

xhr.send(null);
xhr.onreadystatechange = function() {
  if (xhr.status == 200) {
    if (xhr.readyState == XMLHttpRequest.LOADING){
      console.log('response',xhr.response);
      // this can be also binary or your own content type 
      // (Blob and other stuff)
    }
    if (xhr.readyState == XMLHttpRequest.DONE){
      console.log('response',xhr.response);
    }
  }
}

Ajax를 하고 "Ajax" (Ajax 을를사파것다입니생요업됨트이령는용일을 하는 것입니다.setInterval값을 가져오려면 진행률 표시줄을 업데이트합니다.

언급URL : https://stackoverflow.com/questions/9152373/php-flushing-while-loop-data-with-ajax

반응형