0

My client is an entrepeneur and has no html knowledge. He has a website that was created with PHP on a linux shared hosting environment (basic package). On his site he wants to show his previous jobs with photos. But he complains he finds it to hard to login as admin and uploads those photos himself.

-now he asks me to write something easy for him so that the photos in his Dropbox account are uploaded on his site. I said OK :)

I created an admin page ( Here my client can choose which dropbox album he wants to download to his site. ) -I have used the dropbox api for php to locate his photo-albums. -I made a form where I list those albums with submit buttons that will do a POST-request(parameter = path to file on dropbox account).

Here is the code for that request:

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'));
            }
        }
    }
}

This works fine for small files, but throws this exception when the album is too large:

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] 

What is the best thing to do now?? -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.

-upload each photo individually?

-switching to dedicated server means I have full control? I don't know if my client likes to pay 125€ extra/month

aapbee
  • 21
  • 4
  • Have you tried setting the [max execution time](http://php.net/manual/en/function.set-time-limit.php) in the script? – Jay Blanchard Dec 15 '14 at 13:39
  • @JayBlanchard Sounds like No. `-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 Dec 15 '14 at 13:40
  • Any change you manage to make to allow more execution time is only going to be pushing the problem under the carpet. Sooner or later an album will grow big enough to exceed the new execution time limit, and you can't keep pushing the execution time up forever. You need to analyse your code and find ways to optimise it so it can do more work in the allotted time. – GordonM Dec 15 '14 at 13:41
  • @MonkeyZeus setting the max execution time in the script overrides the php.ini file and only affects the script that it is set on. – Jay Blanchard Dec 15 '14 at 13:41
  • @JayBlanchard There is very great chance that this functionality, `ini_set()`, has been completely disabled for the end-user, aapbee. – MonkeyZeus Dec 15 '14 at 13:43
  • Maybe so, but the OP can try it. Once he makes the attempt he can make a decision about hosting or major mods to their script. – Jay Blanchard Dec 15 '14 at 13:46
  • when I asked the helpdesk if I could upload my own .ini file they said "no, there are some settings that we could change using a php.ini, however max execution time is not one om them. – aapbee Dec 15 '14 at 14:00
  • @JayBlanchard No, I'm still on localhost and haven't tried it yet. – aapbee Dec 15 '14 at 14:02

2 Answers2

0

A route you can explore is using a commandline script. PHP scripts on the commandline are usually not limited on execution time. So you would use your adminpage to let your client select the Dropbox album. You store those choices somewhere (in the database for example). Your cronjob can do the actual downloading. When its ready, it should remove the entry from the database again or mark it as downloaded. You can then also use this database to show the download status in the admin page.

EDIT: Now that I think about it a bit more, ask him why he finds the upload difficult? Perhaps there is a much more simple sollution to his problem.

qrazi
  • 1,406
  • 1
  • 15
  • 18
  • He already has an admin module where he can create/delete albums and insert new photos. So that will be the solution. But he wants his site to be updated automatically whenever his dropbox synchronizes with the new photos that he has taken on his iOS phone. – aapbee Dec 15 '14 at 15:14
0

I think you should refactor your logic, using also some client-side logic...
You should first download the structure of remote folder (with getMetadataWithChildren()), and store it on disk with some kind of indexing (i.e.: assigning each file/dir to be downloaded a unique id). This task should hopefully terminate within the maximum execution time limit set by your provider...
Then you should build a second script to download the real data, reading the previously downloaded index, one file/dir at a time.
The script should catch the "MAXIMUM EXECUTION TIME" error to signal it has not yet finished it's job... Something like this:

File: "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;
    }
  }
?>

Then, you should call the php script to download data from dropbox repeatedly, until it finishes:

File "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>

Note: this code is a simple attempt to show a possible solution, it contains some pseudocode, it's not at all finished, and, of course, untested... :-) You should also probably use setInterval(), instead of the while (!done) loop, in javascript code...

MarcoS
  • 17,323
  • 24
  • 96
  • 174
  • after reading your answer and http://stackoverflow.com/questions/3030024/maximum-execution-time-for-javascript I will try client-side approach for actual downloading with use of Javascript Web Workers – aapbee Dec 15 '14 at 15:54
  • Perfect. Glad I gave you some inspiration... :-) – MarcoS Dec 15 '14 at 16:09