我想构建一个脚本,以找出FTP服务器上的哪些文件是新文件,哪些文件已经被处理。
对于FTP上的每个文件,我们读出信息,对其进行解析,然后将需要的信息写入到数据库中。这些文件是xml文件,但必须进行翻译。
目前我正在使用mlsd()
来获取列表,但这最多需要4分钟,因为该目录中已经有15.000个文件-每天都会更多。
我想知道是否有更好的可能性,而不是将此列表与我保存在文本文件中的旧列表进行比较。 因为此任务必须“实时”运行,所以每1或2分钟就会结束一次cronjob。如果此方法花费很长时间,将无法正常工作。
解决方案应使用PHP或Python。
def handle(self, *args, **options):
ftp = FTP_TLS(host=host)
ftp.login(user,passwd)
ftp.prot_p()
list = ftp.mlsd("...")
for item in list:
print(item[0] + " => " + item[1]['modify'])
此代码示例已运行4分钟。
答案 0 :(得分:0)
如果FTP是您与服务器的唯一接口,那么没有比您正在做的更好的方式了。
除非您的服务器支持非标准的-t
切换到LIST
/ NLST
命令,否则它们将返回按时间戳排序的列表。
参见How to get files in FTP folder sorted by modification time。
如果下载文件列表花费的时间很长(而不是开始下载)。在这种情况下,您可以请求排序列表,但仅下载前导的新文件,一旦找到第一个已处理的文件,中止列表。
有关如何中止文件列表下载的示例,请参见:
Download the first N rows of text file in ftp with ftplib.retrlines
类似这样的东西:
class AbortedListing(Exception):
pass
def collectNewFiles(s):
if isProcessedFile(s): # your code to detect if the file was processed already
print("We know this file already: " + s + " - aborting")
raise AbortedListing()
print("New file: " + s)
try:
ftp.retrlines("NLST -t /path", collectNewFiles)
except AbortedListing:
# read/skip response
ftp.getmultiline()
答案 1 :(得分:0)
我一直试图避免浏览文件夹以查找可能发生的更改。我更喜欢设置专用的工作流程。当只能添加文件(或现有文件的新版本)时,我尝试使用一种工作流,其中将文件添加到一个目录中,然后再将文件存储到其他目录中。处理可以在文件使用后删除的目录中进行,也可以在将文件从文件夹复制/移动到另一个目录后进行。
作为一个好东西,我还使用了复制/重命名模式:首先使用临时名称(例如,.t
前缀或后缀)复制文件,并在复制结束时重命名文件。这样可以防止尝试处理未完全复制的文件。好的,当线路速度较慢时,它曾经更为重要,但是应尽可能避免出现竞争状况,它允许使用每10秒或更短时间轮询一个文件夹的守护程序。
不确定它在这里是否真的相关,因为它可能需要重构,但是提供了防弹解决方案。