【问题标题】:shared host has fixed maximum execution time; my php script for admin exceeds that共享主机有固定的最大执行时间;我的管理员 php 脚本超过了
【发布时间】:2014-12-15 13:34:48
【问题描述】:

我的客户是一名企业家,没有 html 知识。他有一个使用 PHP 在 linux 共享主机环境(基本包)上创建的网站。在他的网站上,他想用照片展示他以前的工作。但他抱怨他发现很难以管理员身份登录并自己上传这些照片。

-现在他让我为他写一些简单的东西,以便将他 Dropbox 帐户中的照片上传到他的网站。我说好的:)

我创建了一个管理页面(在这里我的客户可以选择他想要下载到他的网站的 Dropbox 相册。) -我使用了 php 的 Dropbox api 来定位他的相册。 - 我制作了一个表格,在其中列出了那些带有提交按钮的专辑,这些按钮将执行 POST 请求(参数 = Dropbox 帐户上文件的路径)。

这是该请求的代码:

if (isset($_POST['AlbumAdd'])) { 
    $name = $_POST['AlbumAdd'];
    //echo "submitted: $name <br>";
    $entry = getClient()->getMetadataWithChildren($name); //dropbox-sdk 
    if ($entry['is_dir']) {

        //for now create file on localhost -> replace with ftp to upload on shared hosting site
        if (!file_exists(__DIR__ . "/../examples/folder" . $name)) { //if !excists create folder on localhost
            mkdir(__DIR__ . "/../examples/folder" . $name, 0777, true);
            //echo "created " . $name  . "on localhost";
        } 
        foreach ($entry['contents'] as $child) {
            $cp = $child['path'];
            $size = $child['size'];
            $cn = basename($cp);
            echo "basename (cn)= " . $cn . " [$size] <br>";
            if (!$child['is_dir']) //files only
            {
                //download from dropbox to localhost 
                getClient()->getFile($cp, fopen(__DIR__ . '/../examples/folder' . $cp, 'w+b'));
            }
        }
    }
}

这适用于小文件,但当专辑太大时抛出此异常:

Fatal error: Maximum execution time of 30 seconds exceeded in C:\wamp\www\dropbox-sdk-php-1.1.4\dropbox-sdk\Dropbox\CurlStreamRelay.php on line 26
TEST OUTPUT:
basename (cn)= 01.mp3 [8.1 MB]
basename (cn)= 02.mp3 [7.3 MB]
basename (cn)= 03.mp3 [6 MB] 

现在最好的事情是什么? - 托管站点的帮助台说他们无法更改最长执行时间的设置。所以更改我的 php.ini 文件是没有意义的。

-单独上传每张照片?

-切换到专用服务器意味着我可以完全控制?我不知道我的客户是否愿意每月额外支付 125 欧元

【问题讨论】:

  • 你试过在脚本中设置max execution time吗?
  • @JayBlanchard 听起来没有。-Helpdesk of the hosting site says they can't change the setting of the maximum execution time. So there is no point in changing my php.ini file.
  • @MonkeyZeus 在脚本中设置最大执行时间会覆盖 php.ini 文件,并且只会影响设置它的脚本。
  • 您设法进行的任何更改以允许更多执行时间只会将问题推到地毯下。一张专辑迟早会变得足够大,超过新的执行时间限制,你不能一直把执行时间推高。您需要分析您的代码并找到优化它的方法,以便它可以在分配的时间内完成更多工作。
  • @JayBlanchard 很有可能这个功能ini_set() 已被最终用户 aapbee 完全禁用。

标签: php dropbox-api execution-time http-post


【解决方案1】:

我认为您应该重构您的逻辑,同时使用一些客户端逻辑...
您应该首先下载远程文件夹的结构(使用 getMetadataWithChildren()),并使用某种索引将其存储在磁盘上(即:为要下载的每个文件/目录分配一个唯一的 id)。此任务有望在您的提供商设置的最大执行时间限制内终止...
然后你应该构建第二个脚本来下载真实数据,读取之前下载的索引,一次一个文件/目录。
脚本应该捕获“MAXIMUM EXECUTION TIME”错误以表明它还没有完成它的工作......像这样的东西:

文件:“download_data_from_dropbox.php”

<?php
  register_shutdown_function('shutdown');

  global $id;
  DOWNLOAD_DATA($id);
  echo json_encode(array("done" => 1);
  exit 0;

  function shutdown() {
    $e = error_get_last();
    if ($e == "max_execution_time") {
      echo json_encode(array("lastId" => $id);
      exit 0;
    }
  }
?>

然后,您应该调用 php 脚本重复从 Dropbox 下载数据,直到完成:

文件“index.html”:

<html>
  <head>
  </head>
  <body>
  ...
  <div id="status"></div>
  ...
  <script>
  $(document).ready(function() {
      var done = false, id = '',
      while (!done) {
          var url = "download_data_from_dropbox.php?id=" + id;
          $.ajax({
              url: url,
              dataType: 'json',
          }).done(function(response) {
              if (response.done === 1) {
                  // php script is done
                  done = true;
              }
              $("#status").html("Downloading data, last file ID is " + response.lastId   + " ...");
          }).fail(function(jqXHR, textStatus) {
              $("#mybox").html("Error while downloading data: " textStatus);
              done = true;
          });
      }
  });
  </script>
  </body>
</html>

注意:这段代码只是为了展示一个可能的解决方案,它包含一些伪代码,它还没有完成,当然,未经测试... :-)您还应该在 javascript 代码中使用 setInterval(),而不是 while (!done) 循环...

【讨论】:

  • 在阅读您的回答和stackoverflow.com/questions/3030024/… 之后,我将尝试使用 Javascript Web Workers 进行实际下载的客户端方法
  • 完美。很高兴我给了你一些灵感...... :-)
【解决方案2】:

您可以探索的路线是使用命令行脚本。命令行上的 PHP 脚本通常不受执行时间的限制。因此,您将使用您的管理页面让您的客户选择 Dropbox 相册。您将这些选择存储在某处(例如在数据库中)。您的 cronjob 可以进行实际下载。准备就绪后,它应该再次从数据库中删除该条目或将其标记为已下载。 然后,您还可以使用此数据库在管理页面中显示下载状态。

编辑: 现在我想多了,问他为什么觉得上传很困难?也许他的问题有一个更简单的解决方案。

【讨论】:

  • 他已经有一个管理模块,他可以在其中创建/删除相册和插入新照片。所以这将是解决方案。但他希望只要他的保管箱与他在 iOS 手机上拍摄的新照片同步,他的网站就会自动更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多