php如何测试文件是否已完全上传

时间:2012-04-01 13:09:18

标签: php

有没有办法检查文件是否已完全上传到服务器上?我的场景:用户通过ftp上传文件,我的其他PHP任务在cronjob中运行。现在我想检查文件是否已上传或用户是否仍在上传。这是必不可少的,因为我知道我是否可以使用该文件或等到它上传。谢谢。

11 个答案:

答案 0 :(得分:31)

如果您可以控制执行上传的应用程序,则可以要求将文件上传到name.tmp,完成上传后将其重命名为name.final。您的PHP脚本只能查找*.final个名称。

答案 1 :(得分:20)

我有相同的情况,并找到了一个适合我的快速解决方案:

当文件通过FTP上传时,filemtime($yourfile)的值会不断修改。当time() minus filemtime($yourfile)超过X时,上传已停止。在我的场景中,30对于x来说是一个很好的值,你可能想要使用任何不同的值,但它应该至少有3个。

我知道这种方法并不能保证文件的完整性,但是,除了我之外,没有人会上传,我敢于认为。

答案 2 :(得分:14)

如果你在linux上运行php,那么lsof可以帮助你

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

编辑:如果有权限问题。通过使用sudo或suid方法,php脚本可以获得执行lsof命令所需的权限。要设置suid,你必须以root身份发出以下命令。

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

答案 3 :(得分:10)

有许多不同的方法可以解决这个问题。仅举几例:

  1. 使用在上传之前创建的signal file,并在完成后将其删除。
  2. 找出您的FTP server是否有configuration option,例如为未完成的文件提供扩展名“.part”或将文件锁定在文件系统级别(如vsftp)。
  3. 通过解析UNIX / Linux lsof命令的输出获取该目录中所有当前打开文件的列表,并检查您正在检查的文件是否在该列表中(将Nasir的评论从上面考虑到如果遇到权限问题)。
  4. 检查该文件的last modification是否超过特定阈值。
  5. 由于您的用户似乎可以使用他们想要的任何FTP客户端,因此无法使用第一种方法(信号文件)。第二个和第三个答案需要更深入地了解UNIX / Linux并且是系统依赖的。

    所以我认为method #4是进入PHP的方法,只要处理延迟(取决于配置的阈值)没有问题。它很简单,不依赖于任何外部命令:

    // 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();
    }
    

    我希望这可以帮助任何有此问题的人。


    类似的问题:

    Verify whether ftp is complete or not?

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

答案 4 :(得分:4)

一种可能的解决方案是使用循环每隔几秒检查文件大小,如果两个循环之间的大小相同则假定它已上传。

类似的东西:

    $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);

}

答案 5 :(得分:3)

您可以使用以下命令设置线程以获取详细信息: ll -h

获取size列并在一定时间间隔后比较它,如果它在2或3个时间间隔内保持不变,则上传可以完成。

如果您需要更精确的解决方案,并且如果您正在寻找更强大的复杂方式(但效率),请查看以下内容:

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

您可以在我提供的链接中查看此example, 您需要检查事件代码IN_CLOSE_WRITE

取自: LINUX: how to detect that ftp file upload is finished

答案 6 :(得分:2)

保持修改日期的sql记录,并检查你是否有新修改过的文件。

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

答案 7 :(得分:0)

通过检查上传错误消息,您可以确认文件已完成上传或部分上传

如果上传错误代码为3,则部分上传文件

假设您的文件上传字段名称为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
}

在案例3中,您可以检查部分上传

如果您想通过FTP程序跟踪文件上传,如果您正在运行VSFTPD,那么您可以跟踪

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

理解中的任何问题请回复

答案 8 :(得分:-1)

按下一个代码上传后检查文件

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

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

endif;

注意:你必须改变你的图像路径,

祝你好运:)

答案 9 :(得分:-5)

同意Hasan。您可以使用php的file_exist函数进行检查。

保存用户上传文件(或重命名文件,如果要重命名)时所获得的文件名到数据库中的任何表。现在,您的cron每次运行时都会从数据库表中获取该名称,并检查该文件是否已上传。

<?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.
}
?>

答案 10 :(得分:-6)

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