2017-12-30 17 views
0

나는 사용자가 서버 측에있는 사진 아카이브를 만들고 PHP가 끝날 때까지 무슨 일이 일어 났는지 모른 채 화이트 아카이브를 기다리지 않고이 아카이브를 다운로드 할 수있게하려고 노력 중이다.PHP가 사진 아카이브를 만들기 전에 어떻게 페이지를로드 할 수 있습니까?

나는 index.html에서 html 형식의 사진 목록을 얻었습니다.

<form action="include/download_archive.php" method="POST" id="downloadForm"> 
     <input type="hidden" name="downloadForm" value="downloadForm"> 
     <ul id="photos"> 
//JavaScript populates this list with photos once the document is ready. 
     </ul> 
    </form> 

또한 양식을 제출하는 자바 스크립트 기능을 트리거하는 버튼이 있습니다. PHP는 페이지 양식 제출을 처리 (예를 들어 download_archive.php)에

document.getElementById('downloadForm').submit(); 

, 나는 아카이브에 다운로드 링크를 제공하는 다음 아카이브를 생성하고, 이미지의 배열을 읽고 있어요.

if(isset($_POST['downloadForm']) && $_POST['downloadForm']=="downloadForm"){ 
     ignore_user_abort(true); 
     ini_set('max_input_vars','500000'); 
     set_time_limit(0); 
     //Checking if the zip already exists and remove it 
     if(file_exists('../collections/Zips/'.$collection.'.zip')) 
      unlink('../collections/Zips/'.$collection.'.zip'); 
     //Get the array of images 
     $images = $_POST['images']; 
     //Push the images into a new array with the correct path 
     foreach($images as $image => $value) { 
      array_push($files, "../collections/".$collection."/".$value); 
     } 
     //Create a new archive 
     $zip = new ZipArchive; 
     $zip->open('../collections/Zips/'.$collection.'.zip', ZipArchive::CREATE); 
     //Add the files to the archive 
     foreach ($files as $file) { 
      $zip->addFile($file); 
     } 
     //Store the relative location to the zip file 
     $zipPath = '../collections/Zips/'.$collection.'.zip'; 
     //If the zip was succesfully closed, echo a download link. 
     if($zip->close()){ 
      $link = BASE_URL2."collections/Zips/".$collection.'.zip'; 
      $link = str_replace(" ", "%20", $link); 
      echo "<a href='".$link."'>Download photos</a>"; 
     } 

주요 문제는 메인 페이지에있는 사진을 선택하고 "다운로드"버튼을 누르면 한 번 양식이 자바 스크립트에 의해 제출되고 있다는 점이다. 나는 전체 PHP 스크립트가 완료 될 때까지 메인 페이지에서 거기서 기다릴 것이고, 그런 다음에 만 PHP 페이지로 리디렉션됩니다.

저는 PHP 페이지에서 아카이브 생성을 처리하는 폼이 있다고 생각했습니다. 파일 폼이 기본 폼 제출을 통해 가져올 것이고 PHP 페이지가 완전히로드되면 가져올 API 요청을 내부 양식,하지만 이러한 작업 (파일 배열)을 통해 데이터를 유지하는 데 문제가 있습니다.

나는 asynch PHP에 대해서도 생각했지만 소켓 방식 이외의 방법으로는 제한된 것으로 처리 할 방법을 찾을 수 없었다.

나는 그것을 과도하게 만들었다 고 생각하는데, 어떻게 이것을 할 수 있습니까?

답변

1

exec를 사용하여 스크립트를 실행하여 백그라운드에두고 다음 페이지로 이동할 수 있습니다. 이 페이지에서 아약스는 스크립트 완료를 확인하고, 사용자에게 메시지가 나올 때 어떤 일이 일어나고 있는지 알 수 있도록 할 수 있습니다. 스크립트가 완료되면; 귀하의 페이지는 그 파일을 다운로드하기위한 링크로 업데이트 할 수 있습니다.

exec('nohup /var/.../script.php > /dev/null 2> /dev/null & echo $!'); 

그러면 스크립트가 백그라운드 프로세스로 실행되며 페이지를 기다릴 필요가 없습니다.

당신은 심지어 당신이 끝날 때까지 당신이 당신의 페이지로 다시 전달하고 다음 페이지 설문 조사를 할 수있는 $pid = exec($command ,$op); 또는 $pid = (int)$op[0];를 사용하여 실행 프로세스 ID 얻을 수 있습니다 :

$command = 'ps -p '.$pid; 

exec($command, $op); 

if (! isset($op[1])) { 
    // process finished 
} 
else { 
    // still running 
} 

확인을 - 여기 내입니다 완벽하게 작동 답 :

의 index.php :

<?php 
exec('nohup php run.php > /dev/null 2> /dev/null & echo $!', $op); 

$pid = (int)$op[0]; 

header('location: check.php?pid='.$pid); 

run.php :

<?php 

sleep(5); 

check_process.php :

<?php 
header("HTTP/1.1 200 OK"); 

$pid = $_REQUEST['pid']; 

$command = 'ps -p '.$pid; 

exec($command, $op); 

if (! isset($op[1])) { 
    $output = 'script finished'; 
} 
else { 
    $output = 'script running'; 
} 

print $output; 

확인하시기 바랍니다.ph :

<!doctype html> 

<html lang="en"> 
<head> 
    <meta charset="utf-8"> 

    <title>Check</title> 
</head> 

<body> 

<div id="result"></div> 

<script> 

check_process('<?=$_REQUEST['pid']?>'); 

function check_process(pid) { 

    console.log('pid: '+pid); 
    var xmlhttp = new XMLHttpRequest(); 

    xmlhttp.onreadystatechange = function() { 
     if (xmlhttp.readyState == XMLHttpRequest.DONE) { 
      if (xmlhttp.status == 200) { 
       if(xmlhttp.responseText == 'script running') { 
        check_process(pid); 
       } 
       document.getElementById("result").innerHTML = xmlhttp.responseText; 
      } 
      else if (xmlhttp.status == 400) { 
       alert('There was an error 400'); 
      } 
      else { 
       alert('something else other than 200 was returned'); 
      } 
     } 
    }; 

    xmlhttp.open("GET", "check_process.php?pid="+pid, true); 
    xmlhttp.send(); 
} 

</script> 
</body> 
</html> 

이들 모두를 동일한 디렉토리에두고 index.php를 엽니 다. 예를 들어 5 초 동안 잠자기 상태가되는 백그라운드 프로세스가 생성됩니다. 스크립트가 실행중인 페이지가 표시됩니다. 스크립트가 죽을 때; 완료되었다는 것을 알리기 위해 페이지를 업데이트합니다. 이게 도움이 되길 바란다. 그래도 궁금한 점이 있으면 알려주세요.

+0

나는 대답을 받아들이지 않았지만, 작동하는 것으로 들리더라도, 나는이 접근법을 사용하여 PHP 스크립트를 실행하지 못했습니다. 이것을 사용하여 나를 걸을 수있는 간단한 예제/링크가 있습니까? – 1istbesser

+0

잠시만 기다려주십시오. 좀 더 자세한 예제를 작성하고 답변을 업데이트하겠습니다 ... – Phright

+0

OK - 전적으로 작동하는 예제를 작성했습니다. 문제가 있으면 알려주세요. – Phright

관련 문제