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

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

主要问题是,一旦我选择主页上的照片并点击“下载”按钮,表单就会通过 JavaScript 提交。我必须在主页上等待,直到整个 PHP 脚本完成,然后我才会重定向到 PHP 页面。

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

我也考虑过异步 PHP,但除了似乎有限的套接字方式之外找不到其他方法来处理它。

我认为我把它弄得太复杂了,我怎样才能做到这一点?

最佳答案

您可以使用 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);

运行.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;

检查.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。它将生成一个后台进程,例如,该进程将休眠五秒钟。它将带您到一个显示脚本正在运行的页面。当脚本消失时;它会更新页面以告诉您它已完成。我希望这有帮助。如果您有任何疑问,请告诉我。

关于javascript - 如何在 PHP 开始创建照片存档之前加载页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48035186/

相关文章:

php - 插入时准备好的语句错误

php - Web 应用程序开发的优化策略

javascript - PHP 将字符串转换为变量,检查它的值是否不为空,与其他值进行比较

asp.net - 在 UpdatePanel 中阻止 ASP.net __doPostback() 执行 jQuery Submit()

javascript - 重定向到远程表单,填写并提交

javascript - d3 自定义刻度线(基于nextSibling)

javascript - 在html文本框中,如何显示本身包含 ""符号的值?

javascript - 可编辑解析未定义的混合 KnockOutJS 和纯 Javascript

javascript - React - 复选框输入未正确更新(由于浅合并)

php - 如何遍历数组以插入数据库