我有一位客户将文件通过 ftp 传输到我们的服务器。我定义了一个路由来从此目录中选择某些文件并将它们移动到另一个目录进行处理。问题是它一看到它就立即获取它,而不会等到 ftp 完成。结果是 to uri 中描述的路径中的 0 字节文件。我已经尝试了每个 readLock 选项(masterFile、rename、changed、fileLock),但没有一个起作用。我正在使用 spring DSL 来定义我的骆驼路线。这是一个不起作用的示例。骆驼版本是2.10.0
<route>
<from uri="file:pathName?initialDelay=10s&move=ARCHIVE&sortBy=ignoreCase:file:name&readLock=fileLock&readLockCheckInterval=5000&readLockTimeout=10m&filter=#FileFilter" />
<to uri="file:pathName/newDirectory/" />
</route>
如有任何帮助,我们将不胜感激。谢谢!
请注意...一度该路由在另一台服务器上运行,我必须将文件 ftp 到另一台处理该文件的服务器。当我在camel中使用ftp组件时,这条路线工作得很好。也就是说,它会等到收到文件后再执行 ftp。我在定义的路线上有相同的选项。这就是为什么我认为应该有一种方法可以做到这一点,因为 ftp 组件使用了camel 中的文件组件选项。
我采纳了@PeteH 的建议 #2 并执行了以下操作。我仍然希望有另一种方法,但这会起作用。
我添加了以下方法,该方法返回一个 Date,即 current.minus(x 秒)
public static Date getDateMinusSeconds(Integer seconds) {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, seconds);
return cal.getTime();
}
然后在我的过滤器中检查初始过滤是否正确。如果是,我将上次修改日期与 getDateMinusSeconds() 进行比较。如果比较为真,我会为过滤器返回 false。
if(filter){
if(new Date(pathname.getLastModified()).after(DateUtil.getDateMinusSeconds(-30))){
return false;
}
}
我没有在您的环境中执行过任何此类操作,但之前在使用 FTP 时遇到过此类问题。
我建议的两个更好的选择是,如果您能让客户发送两个文件。 File1 是他们的数据,File2 可以是任何东西。他们按顺序发送。当 File2 到达时,您陷入困境,但您所做的只是将其用作 File1 已安全到达的“信号”。
不太好的选择(这是我们最终实现的选择,因为我们无法控制发送的文件)是编写代码,以便拒绝处理任何文件,直到其最后修改的时间戳至少为 x分钟老了。我想我们最终决定是 5 分钟。这是非常可怕的,因为你实际上是在解雇、检查、睡觉、检查等等。
但是您描述的问题在 FTP 中是众所周知的。就像我说的,我不知道这些方法是否适用于您的环境,但在高水平上它们肯定是合理的。
camel继承自文件组件。这是在顶部描述这件事..
请注意,JDK 文件 IO API 在检测另一个应用程序当前是否正在写入/复制文件方面有一些限制。并且根据操作系统平台的不同,实现也可能有所不同。这可能导致 Camel 认为该文件没有被另一个进程锁定并开始使用它。因此,您必须自己调查什么适合您的环境。为了帮助解决这个问题,Camel 提供了不同的 readLock 选项和 didFileName 选项供您使用。另请参阅从其他人直接放置文件的文件夹中使用文件部分。
为了解决这个问题,我让出版商发布了一个“完成”文件。这解决了这个问题
这样做的一种方法是使用观察程序,一旦文件被释放,该观察程序就会触发作业,并将文件的消耗延迟很长一段时间,以确保它的上传完成。
from("file-watch://{{ftp.file_input}}?events=CREATE&recursive=false")
.id("FILE_WATCHER")
.log("File event: ${header.CamelFileEventType} occurred on file ${header.CamelFileName} at ${header.CamelFileLastModified}")
.delay(20000)
.to("direct:file_processor");
from("direct:file_processor")
.id("FILE_DISPATCHER")
.log("Sending To SFTP Uploader")
.to("sftp://{{ftp.user}}@{{ftp.host}}:{{ftp.port}}//upload?password={{ftp.password}}&fileName={{file_pattern}}-${date:now:yyyyMMdd-HH:mm}.csv")
.log("File sent to SFTP");
任何时候回应都不晚。 希望它可以帮助那些在 SFTP 世界最令人毛骨悚然的地方苦苦挣扎的人......
我的服务器上的一个文件夹中有 20 个文件入站。某些文件是在读取操作完成之前发送的。我尝试了“readLock”参数,似乎只要文件不超过200K就可以工作。我今天增加了参数编号,看看是否可以清除所有文件的这个问题。
readLock=changed&
readLockCheckInterval=600000&
readLockTimeout=1200000&
readLockMinAge=3000s&
另一个选项是“doneFileName”参数。这对我有用,但它也传输了扩展名为“.done”的空文件。我的客户说这是不可接受的。