1

I'm building a forum that will allow users to upload images. Images will be stored on my web server temporarily (so I can upload them with a progress bar) before being moved to an S3 bucket. I haven't figured out a brilliant way of doing this, but I think the following makes sense:

  1. Upload image(s) to the web server using XHR with progress bar
  2. Wait for user to submit his post
  3. Unlink images he did not end up including in his post
  4. Call a URL that uploads the remaining images to S3 (and update image URLs in post body when done)
  5. Redirect user to his post in the topic

Now, since step 4 can take a considerable amount of time, I'm looking for a cron like solution, where I can call the S3 upload script in the background and not have the user wait for it to complete.

Ideally, I'm looking for a solution that allows me to request a URL within my framework and pass some image id's in the query, i.e.:

http://mysite.com/utils/move-to-s3/?images=1,2,3

Can I use a cURL for this purpose? Or if it has to be exec(), can I still have it execute a URL (wget?) instead of a PHP script (php-cli)?

Thanks a heap!

oscaralexander
  • 307
  • 2
  • 11

3 Answers3

1

PHP's

  register_shutdown_function()

is your friend [reference].

The shutdown function keeps running, while your script terminated.

Thus, if everything is available, submit the finale page and exit. The the registered shutdown function continues and performs the time-consuming job.

In my case, I prepared a class CShutdownManager, which allows to register several method to be called after script termination. For example, I use CShutdownManager to delete temporary files no longer needed.

SteAp
  • 11,853
  • 10
  • 53
  • 88
  • Never heard of that but it sounds like it's *exactly* what I need :) Thanks! – oscaralexander Nov 09 '11 at 23:30
  • Few people ever used this method. And there's more interesting stuff to discover ;-) Don't forget to vote and accept the answer... – SteAp Nov 09 '11 at 23:31
  • Oh, what I can't seem to find in the manual though: will the shutdown function still be executed if I call a header redirect instead of an exit? As said, I need to redirect the user to the topic page after processing his post. – oscaralexander Nov 09 '11 at 23:37
  • A header( 'Location: http://...' ) does not terminate the running script. To actually send the HTTP reply, you should exit; immediately after the header() call. The shutdown script runs, when you call exit. Thus: Yes. – SteAp Nov 09 '11 at 23:42
  • Don't forget that header() just sets certain HTTP-reply parameters. It does not change the control flow of your PHP-script. – SteAp Nov 09 '11 at 23:43
  • I'm sorry I had to revoke my acceptance; the script will wait for the shutdown function to finish before redirecting the user and does therefore not solve the "and not have the user wait for it to complete" part of the problem. – oscaralexander Nov 13 '11 at 14:01
  • Can't believe. Did you call exit(); after the header() statement? You need to. Could you post your code or a test case? – SteAp Nov 13 '11 at 19:48
  • OK, may be true. Certain web-server - most likely on win-32 - do wait for for script termination before flushing buffers. One more reason why not use win-32 ;-) – SteAp Nov 13 '11 at 21:05
  • Haha, I'm actually running Apache on Mac OS/BSD (MAMP). And yes, I did `exit()` after setting the location header. Let's say we both learned from this ;) – oscaralexander Nov 13 '11 at 23:03
  • Absolutely! I'm going to investigate... Did you try calling flush() before the exit;? – SteAp Nov 14 '11 at 22:53
0

Try the following statement:

shell_exec(php scriptname);
Jonathan Spooner
  • 7,682
  • 2
  • 34
  • 41
Poonam
  • 1
0

I found the solution to this problem which I'm happy to share. I actually found it on SO, but it needed some tweaking. Here goes:

  1. The solution requires either exec() or shell_exec(). It doesn't really matter which one you use, since all output will be discarded anyway. I chose exec().

  2. Since I am using MAMP, rather than a system-level PHP install, I needed to point to the PHP binary inside the MAMP package. (This actually made a difference.) I decided to define this path in a constant named PHP_BIN, so I can set a different path for local and live environments. In this case:

    define(PHP_BIN, '/Applications/MAMP/bin/php/php5.3.6/bin/php');

  3. Ideally, I wanted to execute a script inside my web framework instead of some isolated shell script. I wrote a wrapper script that accepts a URL as an argument and named it my_curl.php:

    if(isset($argv[1]))
    {
        $url = $argv[1];
    
        if(preg_match('/^http(s)?:\/\//', $url))
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_exec($ch);
            curl_close($ch);
        }
    }
    
  4. In this SO question I found the way to execute a shell command in the background. This is necessary because I don't want the user to have to wait until it's finished.

  5. Finally, I run this bit of PHP code to execute the other (or ANY) web request in the background:

    exec(PHP_BIN . ' /path/to/my_curl.php http://site.com/url/to/request
    &> /dev/null &');
    

Works like a charm! Hope this helps.

Community
  • 1
  • 1
oscaralexander
  • 307
  • 2
  • 11