You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Spring Integration SFTP上传文件时写入失败问题求助

Spring Integration SFTP上传失败(No such file)

问题场景

为测试需求,使用Docker部署emberstack/sftp作为SFTP服务器,容器配置如下:

sftp:
  image: emberstack/sftp
  volumes:
    - ./data/sftp.json:/app/config/sftp.json:ro
    - ./data/sftptest:/home/demo/sftp:rw
  ports:
    - "2222:22"

基于Spring Boot 2.7.4/Kotlin Coroutines/Java 17,通过Spring Integration实现SFTP上传,核心代码如下:

配置类:

@Configuration // 修正原代码拼写错误:@Confgiuration -> @Configuration
class MyConfig{
// 其他Bean定义

    @Bean
    fun sftpOutboundFlow(): IntegrationFlow {
        return IntegrationFlows
            .from("toSftpChannel")
            .handle(
                Sftp.outboundAdapter(sftpSessionFactory(), FileExistsMode.FAIL)
                    .useTemporaryFileName(false)
                    .remoteDirectory(sftpProperties.remoteDirectory)
            )
            .get()
    }
}

上传网关:

@MessagingGateway
interface UploadGateway {
    @Gateway(requestChannel = "toSftpChannel")
    fun upload(file: File)
}

单元测试代码:

@Test
fun `upload ach batch files to sftp`() = runTest {
    val test = File("src/test/resources/foo.txt")
    log.debug("uploading file: $test, ${test.exists()}")
    uploadGateway.upload(test)
    eventually(5.seconds) {
        Paths.get("./data/sftptest/foo.txt").shouldExist()
    }
}

测试时本地文件存在,但上传抛出异常,核心错误栈:

Error handling message for file [D:\myproject\build\resources\test\foo.txt -> foo.txt]; 
nested exception is org.springframework.messaging.MessagingException: 
Failed to write to '/home/demo/sftp/foo.txt' while uploading the file; nested exception is java.io.IOException: 
failed to write file
...
Caused by: 2: No such file
    at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
    at com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594)

已创建示例项目复现问题,执行docker compose up sftp启动SFTP服务器,运行对应测试类即可复现。

问题原因与解决方案

1. 检查SFTP用户权限配置

emberstack/sftp的sftp.json配置文件中,需确保demo用户拥有目标目录的读写权限,且根目录设置正确。示例配置:

{
  "Users": [
    {
      "Username": "demo",
      "Password": "demo",
      "HomeDirectory": "/home/demo",
      "SshKeys": [],
      "Permissions": [
        "ReadWrite /home/demo/sftp"
      ]
    }
  ]
}

未配置权限会导致用户无法写入目标目录。

2. 调整远程目录配置

若remoteDirectory配置为绝对路径/home/demo/sftp,部分SFTP服务器会因用户根目录限制拒绝访问。建议改为相对路径sftp(相对于用户根目录/home/demo):

.remoteDirectory("sftp")

此时实际上传路径为/home/demo/sftp,与容器挂载目录匹配。

3. 验证容器内目录权限

进入容器检查/home/demo/sftp目录的所有者是否为demo用户:

docker exec -it <sftp容器ID> bash
ls -l /home/demo/

若所有者不符,可在Docker Compose中指定用户UID/GID(需与容器内demo用户一致):

sftp:
  image: emberstack/sftp
  volumes:
    - ./data/sftp.json:/app/config/sftp.json:ro
    - ./data/sftptest:/home/demo/sftp:rw
  ports:
    - "2222:22"
  user: "1000:1000" # 替换为容器内demo用户的UID/GID

4. 启用远程目录自动创建

若目标目录可能不存在,在SFTP outbound adapter中添加自动创建目录配置:

Sftp.outboundAdapter(sftpSessionFactory(), FileExistsMode.FAIL)
    .useTemporaryFileName(false)
    .remoteDirectory("sftp")
    .autoCreateDirectory(true) // 自动创建远程目录

内容的提问来源于stack exchange,提问作者Hantsy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 05:40:37