Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

PHP copy files sync/Async

Posted on 2012-09-14
5
Medium Priority
?
1,122 Views
Last Modified: 2012-09-16
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


--
0
Comment
Question by:SiemensSEN
  • 2
  • 2
5 Comments
 
LVL 20

Accepted Solution

by:
Mark Brady earned 1100 total points
ID: 38400846
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
 
LVL 111

Assisted Solution

by:Ray Paseur
Ray Paseur earned 300 total points
ID: 38401571
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
 

Author Comment

by:SiemensSEN
ID: 38401584
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
 
LVL 20

Assisted Solution

by:Mark Brady
Mark Brady earned 1100 total points
ID: 38402453
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
 

Author Closing Comment

by:SiemensSEN
ID: 38403218
Thank you
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
This article discusses four methods for overlaying images in a container on a web page
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to dynamically set the form action using jQuery.
Suggested Courses
Course of the Month20 days, 17 hours left to enroll

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question