Spring Integration SFTP上传报错:无法写入foo/002.txt.writing
问题排查与解决方案
核心问题分析
报错Failed to write to 'foo/002.txt.writing' while uploading the file根源是No such file,本质是SFTP服务器端的目标目录foo不存在(或应用无权限访问),导致Spring Integration无法创建临时上传文件.writing;轮询重复触发异常是因为文件上传失败后,Spring Integration默认会重试处理未完成的任务。
分步排查与解决
1. 验证SFTP远程目录与权限
- 手动用SFTP客户端(如FileZilla)登录目标服务器,检查:
- 目标路径
foo是否存在(注意:如果是相对路径,需基于SFTP账号的默认登录目录确认绝对路径,比如默认目录是/home/sftp-user,则foo对应/home/sftp-user/foo)。 - 应用使用的SFTP账号对该目录是否拥有读写权限,包括创建文件、子目录的权限。
- 目标路径
2. 开启SFTP自动创建远程目录(最直接解决方法)
Spring Integration的SftpMessageHandler支持自动创建远程目录,只需在配置中开启该功能,即可避免因目录不存在导致的上传失败。
示例Java配置:
@Bean public SftpMessageHandler sftpMessageHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) { SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory); handler.setRemoteDirectoryExpression(new LiteralExpression("foo")); // 目标目录,可改为绝对路径 handler.setAutoCreateDirectory(true); // 开启自动创建远程目录 handler.setTemporaryFileSuffix(".writing"); // 保持默认临时后缀,也可自定义 return handler; }
示例XML配置:
<int-sftp:outbound-channel-adapter id="sftpOutboundAdapter" session-factory="sftpSessionFactory" channel="outputChannel" remote-directory="foo" auto-create-directory="true" temporary-file-suffix=".writing"/>
3. 修正远程路径配置
- 避免相对路径的歧义,直接配置绝对路径(如
/opt/sftp/foo),确保路径指向准确。 - 如果是嵌套多级目录(如
foo/bar/baz),开启auto-create-directory="true"后会自动创建所有不存在的父目录。
4. 解决重复轮询异常
远程目录问题解决后,首次上传成功时,Spring Integration会自动将.writing临时文件重命名为目标文件(如002.txt),轮询触发的异常会自然消失。如果有失败任务残留,可:
- 备份后清理本地
tmp/out目录下的待上传文件。 - 调整Spring Integration的重试策略(如设置最大重试次数),避免无限制重复触发。
5. 可选:自定义临时文件行为
如果不需要使用.writing临时后缀,可通过setTemporaryFileSuffix自定义(如.tmp),但不建议禁用临时文件——该机制是为了保证上传的原子性,避免服务器端出现不完整的文件。
内容的提问来源于stack exchange,提问作者Simeon Leyzerzon
相关产品推荐
相关产品推荐

