如何在PHP开始创建照片存档之前加载页面?

时间:2017-12-30 15:16:40

标签: javascript php forms asynchronous

我试图允许用户创建位于服务器端的照片存档并下载此存档,而无需等到白页同时发生,直到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函数。

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

在处理表单提交的PHP页面(比如download_archive.php)上,我正在阅读图像数组,创建存档,然后提供存档的下载链接。

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>";
        }

主要问题是,一旦我选择了主页上的照片并点击了#34;下载&#34;按钮和表单由javascript提交。我必须在主页上等待,直到整个PHP脚本完成,然后我才会被重定向到PHP页面。

我想在PHP页面上有一个表单来处理存档的创建,我将通过主表单提交获取文件数组,然后当PHP页面完全加载时,向fetch请求内部形式,但我在整个这些操作(文件数组)中保存数据时遇到了问题。

我也考虑过asynch PHP,但是找不到一种方法来处理除socket-way之外的其他方式,这似乎是有限的。

我相信我过度复杂,我怎么能做到这一点?

1 个答案:

答案 0 :(得分: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
}

好的 - 这是我完全正常的答案:

的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;

check.php:

<!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秒钟。它会将您发送到显示脚本正在运行的页面。当剧本死亡时;它会更新页面告诉你它已经完成。我希望这有帮助。如果您有任何疑问,请告诉我。