2017-12-30 51 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> 

フォームを送信するjavascript機能をトリガーするボタンもあります。私は、画像の配列を読んでアーカイブを作成し、そのアーカイブにダウンロードリンクを提供しています、フォームの送信を処理する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>"; 
     } 

主な問題は、一度、私はメインページの写真を選択し、「ダウンロード」ボタンを押すと、フォームにはJavaScriptによって提出されていることです。私は、PHPのスクリプト全体が完了してからPHPページにリダイレクトされるまで、メインページに待機しています。

私は、アーカイブの作成を処理するPHPページ上にフォームを持っていると思っていました。そして、PHPフォームが完全に読み込まれたときにファイル配列を取得しています。内部フォームが、私はこれらの操作(ファイルの配列)全体のデータを維持するのに問題があります。

私はasynch PHPについても考えましたが、制限されていると思われるsocket-way以外の方法を見つけることができませんでした。

私はそれを過度に作成していると信じています。これをどのように達成できますか?

答えて

1

このスクリプトをexecで実行し、バックグラウンドで実行してから、次のページに移動できます。このページでは、ajaxでスクリプトの終了を確認し、ユーザーに何かメッセージが表示されて何かが起こっていることを知ることができます。スクリプトが完了したら、あなたのページは、ファイルをダウンロードするためのリンクで更新することができます。

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 
} 

OKを - ここに私があります完全に動作するの答え:

の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

関連する問題