我使用JSch与Spring集成将文件从我们的Spring引导应用程序存储到SFTP服务器。最近,上传开始失败,出现以下错误:
Caused by: org.springframework.messaging.MessagingException: Failed to write to './user/2023-04-05_04:00:00_TEST_FILE_FOR_UPLOAD_TO_SFTP_PRODLIKE.csv' while uploading the file; nested exception is org.springframework.core.NestedIOException: failed to write file; nested exception is 9: Invalid handle.
at org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:573) ~[spring-integration-file-5.5.12.jar!/:5.5.12]
at org.springframework.integration.file.remote.RemoteFileTemplate.doSend(RemoteFileTemplate.java:353) ~[spring-integration-file-5.5.12.jar!/:5.5.12]
... 166 common frames omitted
Caused by: org.springframework.core.NestedIOException: failed to write file; nested exception is 9: Invalid handle.
at org.springframework.integration.sftp.session.SftpSession.write(SftpSession.java:177) ~[spring-integration-sftp-5.5.8.jar!/:5.5.8]
at org.springframework.integration.file.remote.RemoteFileTemplate.doSend(RemoteFileTemplate.java:582) ~[spring-integration-file-5.5.12.jar!/:5.5.12]
at org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:570) ~[spring-integration-file-5.5.12.jar!/:5.5.12]
... 167 common frames omitted
Caused by: com.jcraft.jsch.SftpException: Invalid handle.
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873) ~[jsch-0.1.55.jar!/:na]
at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594) ~[jsch-0.1.55.jar!/:na]
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:540) ~[jsch-0.1.55.jar!/:na]
at com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492) ~[jsch-0.1.55.jar!/:na]
at org.springframework.integration.sftp.session.SftpSession.write(SftpSession.java:174) ~[spring-integration-sftp-5.5.8.jar!/:5.5.8]
... 169 common frames omitted
令人震惊的是,当我在谷歌上搜索时,我找不到关于这个特定错误的任何信息。我看到了一些类似的结果,但通常不是关于JSch或关于不同的JSch错误。
大多数类似的搜索结果似乎暗示路径有问题,但我看不出我们要写的路径有什么不同或奇怪的地方。
我已经打开了跟踪日志记录,它显示我们正在成功地连接/身份验证(似乎是当它试图写它失败的文件时)。我检查了磁盘空间是否不足,并测试了如何更改文件名和写目录。
在这种情况下,"handle"具体意味着什么?它的有效性规则是什么?
我们的SFTP Impl:public class SftpService {
private SftpMessagingGateway gateway;
@Autowired
public SftpService(SftpMessagingGateway gateway) {
this.gateway = gateway;
}
public boolean writeStreamToFtp(InputStream data, String filename, String path) {
if (gateway == null) throw new IllegalStateException("SFTP Gateway is not initialized");
Message<InputStream> mess = MessageBuilder.withPayload(data)
.setHeader(FileHeaders.FILENAME, filename)
.setHeader("path", path)
.build();
try {
gateway.send(mess);
log.info("successful persistence of report to sftp server");
return true;
} catch (Exception e) {
log.error("failed to persist report to sftp server", e);
return false;
}
}
}
感谢j_b和他的评论,他指出了明显的下一步并使我回到正轨:"检查sftp服务器日志,看看是否有更多有用的调试信息"。
我请求sftp日志,发现如下:
CreateFile() failed!, Error=123, "The filename, directory name, or volume label syntax is incorrect."
不是很有帮助,但它确实证实了这确实是一个路径问题,我的研究表明它可能是。我仔细看了看我想写的文件名:
2023-04-05_04:00:00_TEST_FILE_FOR_UPLOAD_TO_SFTP_PRODLIKE.csv
…我(终于)注意到了冒号。冒号在文件名中无效。删除它们解决了问题。
所以简而言之,'Invalid handle'似乎意味着Jsch无法写入文件。查看您的SFTP日志以获取更多信息。通常是路径或文件名相关问题。