programing

진행률 요소에 AJAX 업로드 상태 표시

bestprogram 2023. 2. 26. 16:25

진행률 요소에 AJAX 업로드 상태 표시

파일을 PHP 스크립트에 업로드하기 위한 AJAX 스크립트가 있습니다.이 스크립트는 실행하는데 최소 10초가 걸릴 수 있습니다.사용자에게 진행 상황을 표시하고 싶습니다.

에서는, 있다.$progress및(1-100)에 됩니다.get_progress()(어느 쪽인가 하면)

는 어떻게 <progress>사용자가 볼 수 있도록 프런트 엔드의 요소

나는 AJAX가 해결책이라고 생각하지만, 나는 도저히 이해할 수 없다.동일한 개체 인스턴스에 액세스할 수 없습니다.

검색하시는 분들을 위한 참고 자료로 여기에 두겠습니다.javascript에 의존하지 않습니다.

<?php

/**
 * Quick and easy progress script
 * The script will slow iterate through an array and display progress as it goes.
 */

#First progress
$array1  = array(2, 4, 56, 3, 3);
$current = 0;

foreach ($array1 as $element) {
    $current++;
    outputProgress($current, count($array1));
}
echo "<br>";

#Second progress
$array2  = array(2, 4, 66, 54);
$current = 0;

foreach ($array2 as $element) {
    $current++;
    outputProgress($current, count($array2));
}

/**
 * Output span with progress.
 *
 * @param $current integer Current progress out of total
 * @param $total   integer Total steps required to complete
 */
function outputProgress($current, $total) {
    echo "<span style='position: absolute;z-index:$current;background:#FFF;'>" . round($current / $total * 100) . "% </span>";
    myFlush();
    sleep(1);
}

/**
 * Flush output buffer
 */
function myFlush() {
    echo(str_repeat(' ', 256));
    if (@ob_get_contents()) {
        @ob_end_flush();
    }
    flush();
}

?>

대량의 데이터 세트를 서버에 업로드하거나 처리하는 작업이 있는 경우, 진척 상황을 서버에 업데이트하면서 작업을 시작하고 서버에서 실행 중인 다른 스크립트(이미지 스케일링/처리 등)를 사용하여 작업을 수행하는 작업 아키텍처를 사용하는 것을 고려해야 합니다.이 경우 한 번에 한 가지 작업을 수행하므로 입력 및 최종 처리된 출력이 있는 작업의 파이프라인이 형성됩니다.

파이프라인의 각 단계에서 태스크 상태는 데이터베이스 내에서 갱신되며, 그 후 오늘날 존재하는 서버 푸시 메커니즘에 의해 사용자에게 전송됩니다.업로드 및 업데이트를 처리하는 단일 스크립트를 실행하면 서버에 부하가 걸리고 사용자도 제한됩니다(브라우저가 닫히면 다른 오류가 발생하면 어떻게 합니까).프로세스가 여러 단계로 분할되면 실패한 작업을 마지막으로 성공한 시점부터 재개할 수 있습니다.

그것을 하는 방법은 여러 가지가 있다.그러나 전체적인 프로세스 흐름은 다음과 같습니다.

여기에 이미지 설명 입력

다음 방법은 제가 퍼스널프로젝트에서 했던 것으로, 이 스크립트는 수천 개의 고해상도 이미지를 서버에 업로드하고 처리하는 데 유효합니다.이 스크립트는 여러 버전으로 축소되어 그 안에 있는 오브젝트를 인식하면서 아마존 s3에 업로드 됩니다.(원래 코드는 python이었습니다)

순서 1:

전송 또는 작업 시작

먼저 콘텐츠를 업로드한 후 간단한 POST 요청을 통해 이 트랜잭션의 트랜잭션 ID 또는 UUID를 즉시 반환합니다.태스크에서 여러 파일 또는 여러 작업을 수행하는 경우 이 단계에서 해당 논리를 처리할 수도 있습니다.

순서 2:

작업을 수행하고 진행 상황을 반환합니다.

트랜잭션 발생 방법을 파악한 후에는 서버 측 푸시 기술을 사용하여 업데이트 패킷을 전송할 수 있습니다.WebSocket 또는 Server Sent Events 중 지원되지 않는 브라우저의 Long Polling에 해당하는 것을 선택합니다.간단한 SSE 방법은 다음과 같습니다.

function TrackProgress(upload_id){

    var progress = document.getElementById(upload_id);
    var source = new EventSource('/status/task/' + upload_id );

    source.onmessage = function (event) {
        var data = getData(event); // your custom method to get data, i am just using json here
        progress.setAttribute('value', data.filesDone );
        progress.setAttribute('max', data.filesTotal );
        progress.setAttribute('min', 0);
    };
}

request.post("/me/photos",{
    files: files
}).then(function(data){
     return data.upload_id;
}).then(TrackProgress);

서버 측에서는 태스크를 추적하는 것을 작성해야 합니다.job_id 및 db로 전송되는 진행 상황을 가진 단순한 작업 아키텍처로 충분합니다.작업 스케줄은 귀하와 라우팅에 맡기고 싶습니다만, 그 후의 개념 코드(상기 코드만으로 충분할 가장 간단한 SSE의 경우)는 다음과 같습니다.

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
/* Other code to take care of how do you find how many files are left 
   this is really not required */
function sendStatusViaSSE($task_id){
    $status = getStatus($task_id);
    $json_payload = array('filesDone' => $status.files_done,
                          'filesTotal' => $status.files_total);
    echo 'data: ' . json_encode( $json_payload ) . '\n\n';
    ob_flush();
    flush();

    // End of the game
    if( $status.done ){
        die();
    }

}

while( True ){
     sendStatusViaSSE( $request.$task_id );
     sleep(4);
}

?>

SSE에 관한 적절한 튜토리얼은, http://html5doctor.com/server-sent-events/ 를 참조해 주세요.

서버에서 업데이트를 푸시하는 방법에 대한 자세한 내용은 서버에서 업데이트를 푸시하는 문제를 참조하십시오.

상기의 설명은 개념적인 설명으로, 이것을 실현하기 위한 다른 방법이 있지만, 이것은 나의 경우 꽤 큰 과제를 해결한 해결책이었다.

요청이 에 ( )) PHP 요청은 AJAX로 얻을.$progressdiscloss.discloss 。

해결 : 을 으로 쓰면 .$_SESSION['some_progress']는 AJAX에 수 .$_SESSION['some_progress'].

JavaScript가 setInterval() ★★★★★★★★★★★★★★★★★」setTimeout()핸들러를 하려면 , AJAX 로서 됩니다.100.

완벽한 해결책은 아니지만 빠르고 쉽게 해결할 수 있습니다.


같은 세션을 동시에 두 번 사용할 수 없으므로 대신 데이터베이스를 사용하십시오.interval'd AJAX 호출을 사용하여 상태를 데이터베이스에 쓰고 거기에서 읽습니다.

오래된 질문이지만 저도 비슷한 욕구가 있었어요.는 php 를 실행하고 .system()이치노

투표도 안 하고 해봤다.

두 번째 Rikudoit 케이스는 다음과 같습니다.

자바스크립트

document.getElementById("formatRaid").onclick=function(){
    var xhr = new XMLHttpRequest();     
    xhr.addEventListener("progress", function(evt) {
        var lines = evt.currentTarget.response.split("\n");
        if(lines.length)
           var progress = lines[lines.length-1];
        else
            var progress = 0;
        document.getElementById("progress").innerHTML = progress;
    }, false);
    xhr.open('POST', "getProgress.php", true);
    xhr.send();
}

PHP

<?php 
header('Content-Type: application/octet-stream');
header('Cache-Control: no-cache'); // recommended to prevent caching of event data.

// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
// Implicitly flush the buffer(s)
ini_set('implicit_flush', true);
ob_implicit_flush(true);
// Clear, and turn off output buffering
while (ob_get_level() > 0) {
    // Get the curent level
    $level = ob_get_level();
    // End the buffering
    ob_end_clean();
    // If the current level has not changed, abort
    if (ob_get_level() == $level) break;
}   

while($progress < 100) {
    // STUFF TO DO...
    echo '\n' . $progress;
}
?>

솔루션은 다음과 같습니다.

  1. Ajax 폴링 - 서버 측에서 진행률을 어딘가에 저장한 후 Ajax 호출을 사용하여 진행률을 정기적으로 가져옵니다.

  2. Server sended events - 서버에서 보낸 출력에서 dom 이벤트를 생성할 수 있는 html5 기능.이 경우 이것이 최선의 해결책이지만 IE 10에서는 지원되지 않습니다.

  3. 스크립트/Iframe 스트리밍 - 장시간 실행 중인 스크립트에서 출력을 스트리밍하려면 iframe을 사용합니다. 이 스크립트는 브라우저에서 일부 응답을 생성할 수 있는 간격으로 스크립트 태그를 출력합니다.

여기에서는 @Jarod Law가 https://stackoverflow.com/a/7049321/2012407에 기재한 것 외에 2가지 우려사항을 추가하려고 합니다.

매우 심플하고 효율적입니다.수정 및 사용 :) 2가지 우려사항은 다음과 같습니다.

  1. 사용하는 것보다setInterval()또는setTimeout()콜백에서 다음과 같은 재귀 콜을 사용합니다.

    function trackProgress()
    {
        $.getJSON(window.location, 'ajaxTrackProgress=1', function(response)
        {
            var progress = response.progress;
            $('#progress').text(progress);
    
            if (progress < 100) trackProgress();// You can add a delay here if you want it is not risky then.
        });
    }
    

    콜이 비동기이기 때문에가 불필요한 순서로 돌아올 수 있습니다.

  2. 에 저축하다$_SESSION['some_progress']는 스마트하고 데이터베이스 스토리지가 필요 없습니다.실제로 필요한 것은 두 스크립트를 동시에 호출하고 PHP에 의해 큐잉되지 않도록 하는 것입니다.그래서 가장 필요한 것은!여기 아주 간단한 데모 예를 올렸습니다.https://stackoverflow.com/a/38334673/2012407

javascript 출력과 스트림 플러시를 고려해 보셨습니까?이렇게 생겼을 거예요.

echo '<script type="text/javascript> update_progress('.($progress->get_progress()).');</script>';
flush();

이 출력은 플래시로 인해 브라우저로 즉시 전송됩니다.장기 실행 중인 스크립트에서 정기적으로 실행해 보면 아름답게 동작할 수 있습니다.

다음으로 가장 효과적이고 간편하며 테스트를 거친 솔루션을 소개합니다.$_SESSION['progress'],session_start()그리고.session_write_close().

  1. 그 아이디어는 우리가 진척을 보존하는 것이다.$_SESSION['progress']다음으로 세션을 잠가 진행상황을 지속적으로 갱신합니다.session_write_close().

  2. 사용하다session_start();반복 시작 시 및session_write_close()를 클릭합니다.

  3. 그런 다음 이 세션 변수 값을 가져옵니다.$_SESSION['progress']다른 스크립트에서 ajax를 경유합니다.

  4. 그리고 progress_bar 등에서 ajax 응답을 통해 결과를 보여줍니다.

이제 몇 가지 코드를 실행해 보겠습니다.

AJAX 요청을 트리거하는 폼/요청 페이지를 만듭니다(request.php).

<div id="demo">
<button type="button" class="button">Do Something</button>
</div>

 $("button").click(function(){
  $.ajax({url: "request-handler.php", success: function(result){
    alert('done');
  }});
});

리퀘스트 리퀘스트 리퀘스트php

$total = 100;
$count = 1;
while(true)
{
    /*write your code
     ....
    here*/


    session_start();
    $percent = ($count *100)/$total;
    $_SESSION["progress"] = number_format((float)$percent, 2, '.', '');
    $_SESSION["progress"] = (int) ceil($percent);
    $count++;
    session_write_close();
}

Ajax에서 진행 상황 확인(front-view.php):

 <div class="progress" style="display: none;">
      <div class="progress-bar progress-bar-striped active" role="progressbar"
      aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width:0%">
        0%
      </div>
    </div>

    <div class="alert alert-success alert-dismissible" style="display: none;">
      <a href="#" class="close" data-dismiss="alert" aria-label="close">&times;</a>
      <strong>Done!</strong> Successfully Done!.
    </div>

<script type="text/javascript">

  var pBar = $(".progress-bar");
  var progress = 0;
  var intervalId = window.setInterval(function(){
    $.get("get-progress.php", function(data, status){
      progress = data;
    });
    if(progress > 0)
    {
      pBar.parent().show();
    } 
    var percent = progress+'%';
    pBar.width(percent);
    pBar.html(percent);
    if(progress >= 100)
    {
      pBar.parent().hide();
     $ (".alert").show();
      clearInterval(intervalId);
    } 
     
  }, 2000);
    
 

       </script> 

흥분하다php:

<?php

session_start();

$progress = $_SESSION['progress'];
if ($progress >= 100) {
    session_start();
    unset($_SESSION['progress']);
}
//output the response
echo json_encode($progress);
?>

웹 어플리케이션에서는 많은 경우 백엔드 시스템에 대한 요구가 있을 수 있으며, 이로 인해 대량의 데이터 검색이나 장기 데이터베이스 프로세스 등의 장기 실행 프로세스가 발생할 수 있습니다.프론트 엔드 Web 페이지가 행업 해, 프로세스가 완료될 때까지 대기하는 경우가 있습니다.이 프로세스 중에 백엔드 프로세스의 진행 상황에 대한 정보를 사용자에게 제공할 수 있으면 사용자 환경이 개선될 수 있습니다.안타깝게도 웹 응용 프로그램에서는 웹 스크립트 언어가 멀티스레딩을 지원하지 않고 HTTP가 스테이트리스이기 때문에 이 작업이 쉽지 않은 것 같습니다.이제 AJAX를 통해 실시간 프로세스를 시뮬레이션할 수 있습니다.

기본적으로 우리는 그 요청을 처리하기 위해 3개의 파일이 필요합니다.첫 번째 스크립트는 실제 장기 실행 작업을 실행하는 스크립트로 진행률을 저장하기 위한 세션 변수가 필요합니다.두 번째 스크립트는 롱런 작업스크립트의 세션 변수를 에코하는 상태 스크립트입니다.마지막은 상태 스크립트를 자주 폴링할 수 있는 클라이언트 측 AJAX 스크립트입니다.

구현에 대한 자세한 내용은 PHP를 참조하여 동적으로 긴 실행 프로세스 진행률을 얻을 수 있습니다.

언급URL : https://stackoverflow.com/questions/7049303/show-ajax-upload-status-on-progress-element