PHP copy files sync/Async

Hello,
  I need some  help and how to do the following...

I have web application where users can copy  files from location A to Location B on the same server. The application passes the date range  to the server method. The server script then get a list of files  that matches the date range and copy those files to the new location .

If the total file size < max value then copy the file synchronously and notify the users when done
else  
-- notify the user that job will be schedule as a batch process
-- execute the copy as separate process


I am making AJAX call to the server and I can copy file from location A->B but I not sure how to spawn off a process to do the copy in a background mode when the size > max Value

Thanks


--
SiemensSENAsked:
Who is Participating?
 
Mark BradyConnect With a Mentor Principal Data EngineerCommented:
Spawning a separate process is quite easy depending on your requirements of course. I wrote an article on it HERE

You could do it all in the one script if you like. You use ajax to make the call to your script which you are already doing. Inside your script you determine the total file size and if it is within the limits, process the files and return your success message, else you spawn off to a new process. This is another script which is called to do the task. See my example in the article for more details but basically, you can call a separate process from within php by using the exec() command.

$pid = exec('php process_files.php' > /dev/null 2>&1 & echo $!');

if (!$pid) {
    // error here
} else {
    // We are done so this script should return something to the caller (ajax)
}

Open in new window



If you plan on advising the caller/user when their files have been copied you can keep track of the process by adding the copy job to a database when it starts it's process, and when it completes you delete the entry. This is done inside the processing script and is just a flag to let you know a job has been started, and finished when complete.

You can use javascript and a timer to do a checkup on that process every 5 seconds or whatever you want. This would be another script that you send an id to and it will check in the database for that id. If it exists then the process is still running, if not it is complete.

That's the basic idea. I recommend passing an id back to the caller in the original call (if you are going to spawn it off) and the processing script can also be passed that same id. Then when it makes it's database entry it will use that identifier so your checkup script can look for that identifier when it checks the DB.

Hope this helps
0
 
Ray PaseurConnect With a Mentor Commented:
Elvin66 has you on the right path here.  A POST-method request can be used to start an asynchronous process.  I have done this successfully with CURL.

<?php // RAY_curl_post_example.php
error_reporting(E_ALL);


// DEMONSTRATE HOW TO USE CURL POST TO START AN ASYNCHRONOUS PROCESS


function curl_post($url, $post_array=array(), $timeout=2, $error_report=FALSE)
{
    // PREPARE THE POST STRING
    $post_string = NULL;
    foreach ($post_array as $key => $val)
    {
        $post_string .= $key . '=' . urlencode($val) . '&';
    }
    $post_string = rtrim($post_string, '&');

    // PREPARE THE CURL CALL
    $curl = curl_init();
    curl_setopt( $curl, CURLOPT_URL,            $url         );
    curl_setopt( $curl, CURLOPT_HEADER,         FALSE        );
    curl_setopt( $curl, CURLOPT_POST,           TRUE         );
    curl_setopt( $curl, CURLOPT_POSTFIELDS,     $post_string );
    curl_setopt( $curl, CURLOPT_TIMEOUT,        $timeout     );
    curl_setopt( $curl, CURLOPT_RETURNTRANSFER, TRUE         );

    // EXECUTE THE CURL CALL
    $htm = curl_exec($curl);
    $err = curl_errno($curl);
    $inf = curl_getinfo($curl);

    // ON FAILURE
    if (!$htm)
    {
        // PROCESS ERRORS HERE
        if ($error_report)
        {
            echo "CURL FAIL: $url TIMEOUT=$timeout, CURL_ERRNO=$err";
            echo "<pre>\n";
            var_dump($inf);
            echo "</pre>\n";
        }
        curl_close($curl);
        return FALSE;
    }

    // ON SUCCESS
    curl_close($curl);
    return $htm;
}


// USAGE EXAMPLE CREATES ASSOCIATIVE ARRAY OF KEY=>VALUE PAIRS
$args["name"]  = 'Ray';
$args["email"] = 'Ray.Paseur@Gmail.com';

// ACTIVATE THIS TO SEE THE ARRAY OF ARGS
// var_dump($args);

// SET THE URL
$url = "http://LAPRBass.com/RAY_bounce_post.php";

// CALL CURL TO POST THE DATA
$htm = curl_post($url, $args, 3, TRUE);

// SHOW WHAT CAME BACK, IF ANYTHING
if ($htm)
{
    echo "<pre>";
    echo htmlentities($htm);
}
else
{
    echo "NO RESPONSE YET FROM $url -- MAYBE BECAUSE IT IS RUNNING ASYNCHRONOUSLY";
}

Open in new window

HTH, ~Ray
0
 
SiemensSENAuthor Commented:
Thanks you.

My application also allow the user to zip and download the files. Can I use the same solution ?.

This is what I would like to do using your solution:

I submit the request with AJAX to the server
The server spawn off the process to perform action
I return an HTML page to the users (popup/dialog)
  -- The page will will have status of the job or a link to the complete job (using the jobID)
      -- it would auto refresh every x second.
      - for ZIP and download it will have a link when complete
      -- for copy -- a status
  -- So, if they close the main tab, they can still keep the popup window.. waiting for the job to complete. If they close all windows the job will still process to completion on the server
0
 
Mark BradyConnect With a Mentor Principal Data EngineerCommented:
Good call Ray. Yeah I use CURL sometimes to. I suggested using exec() as an easier solution so the author doesn't have to instantiate a CURL object then learn how to use it. That being said, I like CURL myself.

SiememsSEN: Yes you can have a script process the files or whatever job you need doing. You can also store the name or address (url) or the finsished files once they have been processed. Once a complete flag has been found then you can send back whatever you want to the caller.

I use a results array to store thing and update it after each job has completed and save it to the database. My checkup script loads that data and checks what has been done. Here's a quick example.

$results = array(
    'complete' => false,
    'files_uploaded' => false,
    'link' => false,
);

Now you will probably want more descriptive stuff in here but this is just to show you the idea.

In your processing script, create the above array in the __construct() of your class or just create it if you don't need to use classes. Perform the first action (I check that the files have been uploaded). When that is finished, mark that node as complete.

$results['files_uploaded' = true;

Once your script processes the files and puts them in their final resting place (sounds like the files have died !) you create the link to them.

$link = 'your_site.com/';

// Add to the results array.
$results['link'] = $link;

When everything is done, mark the job complete.
$results['complete'] = true;

// stringify the results array so you can store it in the Database.

$results = json_encode($results);

// Save to your database in a string or text field somewhere.
// end your script.

In your checkup script you get that string from the database and decode it.

$json = (get the string from the database here)
$results = json_decode($json);

Now you have the original array back and can work with it.

if($results['complete'] {
// this job is complete so get the link from the results and you will need the id or whatever key you want to send back. You can json_encode() an array if you want to send an array for javascript to decode and use or just send back a single string.

To send back a streing with several items in it you could concat the items and separate each one with :: or something. Then in javascript split that string up at the separators and you will have all your required info back.

Hope that helps
0
 
SiemensSENAuthor Commented:
Thank you
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.