Home » Php » php how to test if file has been uploaded completely

php how to test if file has been uploaded completely

Posted by: admin April 23, 2020 Leave a comment

Questions:

Is there any way to check if file has been uploaded completely on the server? My scenario: User uploads file over ftp and my other PHP task is running in cronjob. Now I would like to check if file has been uploaded or if user is still uploading. It is essential because then I know if I can work with that file or wait until it is uploaded. Thank you.

How to&Answers:

If you have control over the application doing the upload, you can require that it upload the file to name.tmp, and when it’s done uploading rename it to name.final. Your PHP script could look only for *.final names.

Answer:

I had the same scenario and found a quick solution that worked for me:

While a file is uploading via FTP, the value of filemtime($yourfile) is continuously modified. When time() minus filemtime($yourfile) is more than X, uploading has stopped. In my scenario, 30 was a good value for x, you might want to use any diferent value, but it should usefully be at least 3.

I do know that this method doesn’t guarantee the file’s integrity, but, as no one but me is going to upload, i dare to assume that.

Answer:

if you are running php on linux then lsof can help you

$output = array();
exec("lsof | grep file/path/and/name.ext",$output);
if (count($output)) {
  echo 'file in use';
} else {
  echo 'file is ready';
}

EDIT: in case of permission issue. by using sudo or suid methods php script can get required permissions to execute lsof command. to set suid you have to issue following command as root.

su root
chmod u+s /usr/sbin/lsof

Answer:

There are many different ways to solve this. Just to name a few:

  1. Use a signal file that is created before the upload and removed when it’s completed.
  2. Find out if your FTP server has a configuration option that for example gives uncompleted files the extension “.part” or locks the file on the file system level (like vsftp).
  3. Get a list of all currently opened files in that directory by parsing the output of the UNIX/Linux lsof command and check if the file you’re checking is in that list (take Nasir’s comment from above into account if you encounter permission problems).
  4. Check if the last modification of that file is longer ago than a specific threshold.

As it seems your users can use any FTP client they want, the first method (signal file) can’t be used. The second and third answers need a deeper understanding of UNIX/Linux and are system dependend.

So I think that method #4 is the way to go in PHP as long as processing latency (depending on the configured threshold) is no problem. It is straightforward and doesn’t depend on any external commands:

// Threshold in seconds at which uploads are considered to be done.
$threshold = 300;

// Using the recursive iterator lets us check subdirectories too
// (as this is FTP anything is possible). Its also quite fast even for
// big directories.
$it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($uploadDir);

while($it->valid()) {
  // Ignore ".", ".." and other directories. Just recursively check all files.
  if (!$it->isDot() && !$it->isDir()) {
    // $it->key() is the current file name we are checking.
    // Just check if it's last modification was more than $threshold seconds ago.
    if (time() - filemtime($it->key() > $threshold)) {
      printf("Upload of file \"%s\" finished\n", $it->key());

      // Your processing goes here...

      // Don't forget to move the file out so that it's not identified as
      // just being completed everytime this script runs. You might also mark
      // it in any way you like as being complete if you don't want to move it.
    }
  }
  $it->next();
}

I hope this helps anyone having this problem.


Similar questions:

Verify whether ftp is complete or not?

PHP: How do I avoid reading partial files that are pushed to me with FTP?

Answer:

A possible solution would be to check the file size every few seconds using a loop, and if the size is the same between two loops assume it’s uploaded.

something like:

    $filesize = array();
    $i = 0;
    while(file_exists('/myfile.ext')) {
    $i++;

    $filesize[$i] = filesize('/myfile.ext');

    if($filesize[$i - 1] == $filesize[$i]) {
    exit('Uploaded');
    }

sleep(5);

}

Answer:

you can set a thread to get details using :
ll -h

and getting the size column and comparing it after a certain time interval if it stays the same for 2 or 3 time interval then the upload could be finished.

if you need a more precise solution and if you are looking for a more complicated way (but efficient) to do it, check this out :

http://www.php.net/manual/en/function.inotify-read.php

You can take a look at this example in the link I gave,
You will need to check for the event code IN_CLOSE_WRITE

Taken from :
LINUX: how to detect that ftp file upload is finished

Answer:

keep sql record of date modified and check if you have newely modified file.

<?php 
$filename = 'somefile.txt';
if (file_exists($filename)) {
echo "$filename was last modified: " . date ("F d Y H:i:s.", filemtime($filename));
}
?>

Answer:

By checking upload error message you can confirm whethere file complete uploaded or partial uploaded

If upload Error Code is 3 then file uploaded partially

let say your file upload field name myfile

$error=$_FILES['myfile']['error'];
if($error>0){
//Upload Error IS Present check what type of error
switch($error){
    case 1:
        // UPLOAD_ERR_INI_SIZE
        // Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.
        break;
    case 2:
        // UPLOAD_ERR_FORM_SIZE
        // Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
        break;
    case 3:
        // UPLOAD_ERR_PARTIAL
        // Value: 3; The uploaded file was only partially uploaded.
        break;
    case 4:
        // UPLOAD_ERR_NO_FILE
        // Value: 4; No file was uploaded.
        break;
    case 6:
        // UPLOAD_ERR_NO_TMP_DIR
        // Value: 6; Missing a temporary folder. Introduced in PHP 4.3.10 and PHP 5.0.3.
        break;
    case 7:
        // UPLOAD_ERR_CANT_WRITE
        // Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.
        break;
    case 8:
        // UPLOAD_ERR_EXTENSION
        // Value: 8; A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help. Introduced in PHP 5.2.0.
        break;
}

}else{
    //File IS Uploaded you can move or validate other things
}

In case 3 you can check partial upload

If you want to Track file Upload Via FTP Programme if you are running VSFTPD then you can track

file=/var/log/vsftpd.log
initial_files=`grep -c 'OK UPLOAD' $file`;
while [ TRUE ]
do
current_files=`grep -c 'OK UPLOAD' $file`;
if [ $current_files == $initial_files ]; then
     echo "old File Not Uploaded";
else
     echo "new File Uploaded Process New File";
new_file=`grep 'OK UPLOAD' $file | tail -1`;
echo $new_file;
initial_files=$current_files;
fi
sleep 1
done

any problem in understanding please reply

Answer:

Check for the file after uploading by next code

if (file_exists('http://www.domain.com/images/'.$filename)) :

    // Write some response as you like as a success message

endif;

Notice: you have to change images path by yours ,

good luck 🙂

Answer:

Agreed with Hasan. You can check it by using php’s file_exist function.

save your filename which your and getting while user uploading a file (or a renamed file if you are renaming it) to any table in database. Now your cron will get that name from database table each time it runs and will check if that file had been uploaded or not.

<?php
$filename = '/var/www/YOUR_UPLOAD_FOLDER/xyz.txt'; //get xyz name from database

if (file_exists($filename)) {
   // YOU CAN WORK WITH YOUR FILE AND CAN DELETE RELATIVE RECORD FROM DB TABLE.
} else {
   // YOU SHOULD WAIT WHILE FILE IS UPLOADING.
}
?>

Answer:

<?php
    if (move_uploaded_file($_FILES["uploader_name"]["tmp_name"], $path_name)):
        //print true condition
    else:
        //print false condition
    endif;
?>