文件正在通过FTP推送到我的服务器。我在Drupal模块中使用PHP代码处理它们。 O / S是Ubuntu,FTP服务器是vsftp。
我将定期检查新文件,使用SimpleXML处理它们并将它们移动到“完成”文件夹。如何避免处理部分上传的文件?
vsftp将lock_upload_files默认为是。我想先尝试移动文件,期望在当前上传的文件中移动失败。这似乎不会发生,至少在命令行上。如果我开始上传大文件并移动,它只会在新位置继续增长。我猜目录条目没有锁定。
我是否应该尝试使用模式'a'或'r +'来查看它是否在尝试加载到SimpleXML之前成功还是有更好的方法来执行此操作?我想我可以检测到SimpleXML加载失败,但......看起来很麻烦。
我无法控制发件人。他们不会上传和重命名。
由于
答案 0 :(得分:4)
使用lock_upload_files
的{{1}}配置选项会导致使用vsftpd
功能锁定文件。这会在正在进行的上传文件上放置咨询锁。其他程序不需要考虑咨询锁,例如fcntl()
不会。咨询锁通常只是关心此类锁的程序的建议。
您需要另一个命令行工具,如mv
,它尊重顾问锁。
注意:必须使用lockrun
宏编译lockrun
以使用WAIT_AND_LOCK(fd)
而不是lockf()
函数才能使用flock()
设置的锁。 Linux下的1}}因此,当使用fcntl()
编译lockrun
时,它将与lockf()
设置的锁合作。
使用此类功能(vsftpd
,lockrun
,mv
),您可以构建一个shell脚本或类似程序,逐个移动文件,检查文件是否已事先锁定并持有只要文件被移动,就会对它进行咨询锁定。如果文件被lock_upload_files
锁定,则vsftpd
可以跳过对lockrun
的调用,以便跳过正在运行的上传。
答案 1 :(得分:3)
如果锁定不起作用,我不知道你想要的解决方案是干净/简单。您可以通过不处理上次修改时间(您可以使用filemtime()
获得)的文件在过去 x 分钟内处理文件,从而做出有根据的猜测。
如果您想要更高的置信度,可以在一个简单的数据库中检查并存储每个文件的大小(使用filesize()
),并且每个 x 分钟检查新的大小它的旧尺寸。如果 x 分钟内的大小没有变化,您可以假设没有其他内容被发送。
答案 2 :(得分:2)
lsof
linux命令列出了系统上打开的文件。我建议用PHP中的shell_exec()
执行它并解析输出以查看FTP服务器仍在使用哪些文件。
答案 3 :(得分:1)
选择上一个答案,您可以复制文件,然后以固定间隔比较复制文件和原始文件的大小。
如果尺寸匹配,则上传完成,删除副本,使用文件。
如果尺寸不匹配,请再次复制文件。
重复。
答案 4 :(得分:0)
这是另一个想法:创建一个可以访问部分或全部上传目录的超级(但希望不是root)FTP用户。而不是您的PHP代码从磁盘上读取上传的文件,使其连接到本地FTP服务器并下载文件。这样,vsftpd会为您处理锁定(假设您启用了lock_upload_files
)。一旦vsftp释放独占/写锁定(写入完成后),您将只能下载文件。
您提到在评论中尝试flock
(以及它如何失败)。尝试匹配vsftpd所做的任何锁定确实显得很痛苦,但dio_fcntl
可能值得一试。
答案 5 :(得分:0)
我猜你几年前已经解决了你的问题,但仍然。
如果您使用某种模式查找所需的文件,您可以要求上传文件的一方使用不同的名称,并在上传完成后重命名该文件。
答案 6 :(得分:0)
您应该在proftp中查看“隐藏的商店”,更多信息在这里: http://www.proftpd.org/docs/directives/linked/config_ref_HiddenStores.html