如何确定文件是否仍在通过ftp传输

时间:2011-08-30 10:43:41

标签: php ftp

我有一个目录,其中包含需要使用PHP批量处理的文件。文件通过FTP复制到服务器上。有些文件非常大,需要很长时间才能复制。如何在PHP中确定文件是否仍在传输(因此我可以跳过该文件的处理并在下一次批处理过程中处理它)?

可能是获取文件大小,等待片刻,并验证文件大小是否不同。这不是防水的,因为转移只是暂时停顿了一会儿......

5 个答案:

答案 0 :(得分:9)

最安全的方法之一是使用临时名称上传文件,并在传输完成后重命名。你的程序应该跳过带有临时名称的文件(一个简单的扩展名就可以了。)显然这需要客户端(上传者)合作,所以它并不理想。

[如果您需要,也可以在给定时间段后删除失败(部分)转移。]

基于轮询文件大小的任何内容都是活泼且不安全的。

另一种方案(也需要上传者的合作)可能涉及首先上传文件的散列和大小,然后是实际文件。这使您可以了解传输何时完成以及是否一致。 (这个想法有很多变种。)

不需要客户合作的东西是检查文件是否被其他进程打开。 (你如何做到这一点取决于操作系统 - 我不知道这样做的PHP内置。lsof和/或fuser可用于各种Unix类型的平台,Windows有API对于这个。)如果另一个进程打开了文件,可能还没有完成。

请注意,如果允许重新启动/恢复上传,或者如果您的FTP服务器软件在整个传输过程中没有保持文件打开,那么最后一种方法可能不是万无一失的,所以YMMV。

答案 1 :(得分:5)

我们的服务器管理员建议使用ftpwho,它输出当前正在传输的文件。

http://www.castaglia.org/proftpd/doc/ftpwho.html

所以解决方法是解析ftpwho的输出以查看目录中的文件是否正在传输。

答案 2 :(得分:4)

某些FTP服务器允许在发生特定事件时运行命令。因此,如果您的FTP服务器允许这样做,那么您可以构建一个简单的信令方案,让您的应用程序知道文件已经或多或少成功上传(或多或少是因为您不知道用户是否打算上传文件完全或部分)。信令方案可以像创建“uploaded_file_name.ext.complete”文件一样简单,您将监视扩展名为“.complete”的文件的存在。

现在,您可以检查是否可以打开文件进行写入。如果要上载文件,大多数FTP服务器都不允许您这样做。

Mat提到的另一种方法是使用特定于系统的技术来检查文件是否被其他进程打开。

答案 3 :(得分:3)

检查的最佳方法是尝试使用flock获取文件的独占锁定。 sftp / ftp进程将使用fopen库。

// try and get exclusive lock on file
$fp = fopen($pathname, "r+");

if (flock($fp, LOCK_EX)) {  // acquire an exclusive lock
    flock($fp, LOCK_UN);    // release the lock
fclose($fp);
}
else {
    error_log("Failed to get exclusive lock on $pathname. File may be still uploading.");
}

答案 4 :(得分:1)

这不是一个很好的技巧,但它很简单:-),你可以用filemtime做同样的事情

$result = false;
$tryies = 5;
if (file_exists($filepath)) {
    for ($i=0; $i < $tryies; $i++) { 
        sleep(1);
        $filesize[] = filesize($filepath);
    }
    $filesize = array_unique($filesize);
    if (count($filesize) == 1) {
        $result = true;
    } else {
        $result = false;
    }
}

return $result;