php 如何确定文件是否仍在通过 ftp 传输
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7241978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to determine whether a file is still being transferred via ftp
提问by murze
I have a directory with files that need processing in a batch with PHP. The files are copied on the server via FTP. Some of the files are very big and take a long time to copy. How can I determine in PHP if a file is still being transferred (so I can skip the processing on that file and process it in the next run of the batch process)?
我有一个目录,其中包含需要使用 PHP 批量处理的文件。这些文件通过 FTP 复制到服务器上。有些文件非常大,需要很长时间才能复制。如何在 PHP 中确定文件是否仍在传输(因此我可以跳过对该文件的处理并在批处理的下一次运行中对其进行处理)?
A possibility is to get the file size, wait a few moments, and verify if the file size is different. This is not waterproof because there is a slight chance that the transfer was simply stalled for a few moments...
一种可能性是获取文件大小,稍等片刻,然后验证文件大小是否不同。这不防水,因为传输有可能只是暂停了几分钟......
采纳答案by murze
Our server admin suggested ftpwho, which outputs which files are currently transferred.
我们的服务器管理员建议使用 ftpwho,它会输出当前传输的文件。
http://www.castaglia.org/proftpd/doc/ftpwho.html
http://www.castaglia.org/proftpd/doc/ftpwho.html
So the solution is to parse the output of ftpwho to see if a file in the directory is being transferred.
所以解决的办法是解析ftpwho的输出,看是否有目录中的文件正在传输。
回答by Mat
One of the safest ways of doing this is to upload the files with a temporary name, and rename them once the transfer is finished. You program should skip files with the temporary name (a simple extension works just fine.) Obviously this requires the client (uploader) to cooperate, so it's not ideal.
执行此操作的最安全方法之一是使用临时名称上传文件,并在传输完成后重命名它们。您的程序应该跳过具有临时名称的文件(一个简单的扩展名就可以了。)显然这需要客户端(上传者)配合,所以并不理想。
[This also allows you to delete failed (partial) transfers after a given time period if you need that.]
[如果需要,这也允许您在给定时间段后删除失败的(部分)传输。]
Anything based on polling the file size is racy and unsafe.
基于轮询文件大小的任何内容都是不安全的。
Another scheme (that also requires cooperation from the uploader) can involve uploading the file's hash and size first, then the actual file. That allows you to know both when the transfer is done, and if it is consistent. (There are lots of variants around this idea.)
另一种方案(也需要上传者的合作)可能涉及先上传文件的哈希值和大小,然后是实际文件。这使您可以知道传输何时完成,以及传输是否一致。(围绕这个想法有很多变体。)
Something that doesn't require cooperation from the client is checking whether the file is open by another process or not. (How you do that is OS dependent - I don't know of a PHP builtin that does this. lsof
and/or fuser
can be used on a variety of Unix-type platforms, Windows has APIs for this.) If another process has the file open, chances are it's not complete yet.
不需要客户端合作的事情是检查文件是否被另一个进程打开。(你如何做到这一点取决于操作系统——我不知道有一个 PHP 内置程序可以做到这一点。lsof
和/或fuser
可以在各种 Unix 类型平台上使用,Windows 有用于此的 API。)如果另一个进程有这个文件打开,可能还没有完成。
Note that this last approach might not be fool-proof if you allow restarting/resuming uploads, or if your FTP server software doesn't keep the file open for the entire duration of the transfer, so YMMV.
请注意,如果您允许重新启动/恢复上传,或者如果您的 FTP 服务器软件没有在整个传输过程中保持文件打开,则最后一种方法可能不是万无一失的,所以 YMMV。
回答by Eugene Mayevski 'Callback
Some FTP servers allow running commands when certain event occurs. So if your FTP server allows this, then you can build a simple signalling scheme to let your application know that the file has been uploaded more or less successfully (more or less is because you don't know if the user intended to upload the file completely or in parts). The signalling scheme can be as simple as creation of "uploaded_file_name.ext.complete" file, and you will monitor existence of files with ".complete" extension.
某些 FTP 服务器允许在发生特定事件时运行命令。因此,如果您的 FTP 服务器允许这样做,那么您可以构建一个简单的信令方案,让您的应用程序知道文件或多或少已成功上传(或多或少是因为您不知道用户是否打算上传文件完全或部分)。信令方案可以像创建“uploaded_file_name.ext.complete”文件一样简单,您将监视具有“.complete”扩展名的文件的存在。
Now, you can check if you can open file for writing. Most FTP servers won't let you do this if the file is being uploaded.
现在,您可以检查是否可以打开文件进行写入。如果正在上传文件,大多数 FTP 服务器将不允许您执行此操作。
One more approach mentioned by Mat is using system-specific techniques to check if the file is opened by other process.
Mat 提到的另一种方法是使用特定于系统的技术来检查文件是否被其他进程打开。
回答by Tedzzz
Best way to check would be to try and get an exclusive lock on the file using flock. The sftp/ftp process will be using the fopen libraries.
检查的最佳方法是尝试使用 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.");
}
回答by daddyy
It's not realy nice trick, but it's simple :-), the same u can do with filemtime
这不是一个很好的技巧,但它很简单:-),你可以用 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;