1

I have a file upload page in my application. I need to show "Uploading" while file is uploading then show "Processing" while file is processing. Then after completion of script my page got redirected to some url.

I have tried to use PHP SESSIONS in the script. As in code below:

$_SESSION['uploaded']=0;
if (!empty($_FILES)) {
    $tempFile = $_FILES['file']['tmp_name'];
    $targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
    $_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name'];
    $targetFile =  $targetPath. $_FILES['file']['name'];
    if(move_uploaded_file($tempFile,$targetFile)){
            $_SESSION['uploaded']=1;
            //some processing here which takes some 4-5second to complete
    }
}

After file upload complete I update session. I am checking session every second by calling following function in javascript:

    function countdown(seconds){
                console.log(<?php echo $_SESSION['uploaded']; ?>);
                if(<?php echo $_SESSION['uploaded']; ?>==0){
                    setTimeout(function() {                        
                        //uploading
                        seconds--;
                        countdown(seconds);
                    }, 1000);                     
                }
                else{
                    //processing
                }
            }

After searching from google for long time I came to know that in a single script SESSION is locked till script execution completed. Then I used session_write_close(); But it also not works. I am always getting 0 value of SESSION.

Please help me figuring out solution in simplest way. Thanks.

UPDATE

Unable to make it work with Ajax request also. So further tried using the MySQL table.

What I do is create table when upload script is called. Then insert value of status=0 in it using following code:

$session=session_id();
$stmt=$conn->prepare("DROP TABLE IF EXISTS $session");    
$stmt->execute();
$stmt=$conn->prepare("CREATE TABLE $session (id INT(11), status INT(11))");    
$stmt->execute();
$stmt=$conn->prepare("INSERT INTO $session VALUES(1,0)");
$stmt->execute();

Then after upload completion I update the status to 1 and do the processing on file. Then after successful completion of script I redirect to result page and drop table using session_id().

But My Ajax script which is checking status every second doesn't respond till the upload.php script ends. I have tried closing connection after every query but in vain. Code on getstatus.php

<?php
    session_start();
    $session=session_id();
    require_once('connect.php');
    $stmt=$conn->prepare("SELECT * FROM $session WHERE id=1");
    $stmt->execute();
    $res=$stmt->fetch(PDO::FETCH_ASSOC);
    echo $res['status'];
?>

Unable to find solution for it till now. Help is greatly appreciated. Thanks.

عثمان غني
  • 2,786
  • 4
  • 52
  • 79

4 Answers4

1

Instead of invoking a PHP process on the server side every second, you could use a static file to check the upload state.

When generating the upload form for the client:

  1. Create a tempnam for a directory that is accessible for the client.
  2. Write 'uploading' to the temporary file
  3. Store the filename in the session. (Be aware: The user might open multiple upload forms. Store the filenames in an array)
  4. Send the filename to the client as a hidden field.

On the server side after user submitted the form:

  1. Check if filename sent from the client matches a filename stored in the session.
  2. Write 'processing' to the state file
  3. At the end of your upload script write 'finished' to the state file

On the client side after user submits the form, check the upload state by doing ajax requests on the state file.

Remarks

Disable caching for the state file with .htaccess. If this is no option you can achieve the same behavior with a php state script and the upload state saved to a session variable instead of a state file.

To make sure all generated files are deleted register a destroy handler that deletes files generated in the session: http://php.net/manual/en/function.session-set-save-handler.php

Gerd K
  • 1,134
  • 9
  • 23
0

<?php echo $_SESSION['uploaded']; ?> is preprocessed by PHP only once, just before this javascript is sent to client. That said, the javascript on client looks like:

function countdown(seconds){
            console.log(0);
            if(0==0){
                setTimeout(function() {                        
                    //uploading
                    seconds--;
                    countdown(seconds);
                }, 1000);                     
            }
            else{
                //processing
            }
        }

You should find other way (ajax?) to update information on the client side.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
0

This became too long for a comment.

I'm unsure how you'd respond with progress information with PHP. I tried once and failed.

Socket.io is awesome in Node.js and there is a PHP server emitter. I would potentially give that a go. It should offer near instantaneous communication without waiting for scripts to complete.

Alternatively I would check out Jquery upload, it has a PHP server script. Supports progress bars Jquery Upload. Either implement it directly or check out the source code for how display progress info. I tried having a quick look but couldn't identify how they do it easily.

Lex
  • 4,749
  • 3
  • 45
  • 66
0

Why use DATABASE if you can do it on server ?

To save your bandwidth and database traffic you can seperate your process into 2 file

  1. Create upload.php to serve uploading process

    $_SESSION['uploaded']=0;
      if (!empty($_FILES)) {
      $tempFile = $_FILES['file']['tmp_name'];
      $targetPath = dirname( __FILE__ ) . $ds. $storeFolder . $ds;
      $_FILES['file']['name']=date('Ymdhis').$_FILES['file']['name'];
      $targetFile = $targetPath. $_FILES['file']['name'];
          if(move_uploaded_file($tempFile,$targetFile)){
             // Save path to session var
              $_SESSION['uploaded']=$targetFile;
            //You can tell client if the uploading process were done and show 'Processing ...' 
               // Place some code
            exit;
          }
    
    }
    
  2. Next, create a file called progress.php

    // check
    if(!empty($_SESSION['uploaded'])){
        // Do your processing code here
    
      // Remove session
      unset($_SESSION['uploaded']);
      // Then send response to client after your processing were done
      echo 'Done';
      exit;
    }
    

    You can redirect client using jquery as you tagged it. Good luck

Mike
  • 1,231
  • 12
  • 17