【问题标题】:Failed to write file when using Spring Integration Sftp to upload files使用 Spring Integration Sftp 上传文件时写入文件失败
【发布时间】:2022-11-05 12:52:55
【问题描述】:

我尝试使用 emberstack/sftpatmoz/sftp 在 Docker 容器中托管 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/Java17。

我已经定义了以下 bean 来上传文件。

@Confgiuration
class MyConfig{
//other beans.

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

// a messaging gateway to send file.
@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
org.springframework.messaging.MessageDeliveryException: 
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, failedMessage=GenericMessage [payload=D:\myproject\build\resources\test\foo.txt, 
....

Caused by: 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
    at app//org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:573)
    at app//org.springframework.integration.file.remote.RemoteFileTemplate.doSend(RemoteFileTemplate.java:353)
    ... 143 more
Caused by: java.io.IOException: failed to write file
    at org.springframework.integration.sftp.session.SftpSession.write(SftpSession.java:176)
    at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.write(CachingSessionFactory.java:237)
    at org.springframework.integration.file.remote.RemoteFileTemplate.doSend(RemoteFileTemplate.java:601)
    at org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:570)
    ... 144 more
Caused by: 2: No such file
    at app//com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)
    at app//com.jcraft.jsch.ChannelSftp._put(ChannelSftp.java:594)
    at app//com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:540)
    at app//com.jcraft.jsch.ChannelSftp.put(ChannelSftp.java:492)
    at app//org.springframework.integration.sftp.session.SftpSession.write(SftpSession.java:173)
    ... 147 more

更新:我创建了一个sample project 来产生这个问题。

运行以下命令启动 sftp。

docker compose up sftp 

运行测试SftpIntegrationFlowsTest 以产生问题。

【问题讨论】:

  • FTP服务器认证成功了吗?
  • 您发布的例外情况并不多。您是否可以尝试打印内部异常(递归),直到您拥有所有内容并将其发布在这里?
  • 我看到“没有这样的文件”,可能在batchGateway.upload(test) 之前检查文件是否存在
  • 那么这个文件'/home/demo/sftp/foo.txt' 存在吗?然后尝试chmod 777它只是为了测试

标签: spring-boot kotlin spring-integration spring-integration-sftp


【解决方案1】:

对我有用(确保要上传的目标文件的路径正确):

public static DefaultSftpSessionFactory sftpSessionFactory() {
    DefaultSftpSessionFactory sessionFactory = new DefaultSftpSessionFactory();
    sessionFactory.setHost("hostip");
    sessionFactory.setPort(65002); //might be 22 as well
    sessionFactory.setAllowUnknownKeys(true);
    sessionFactory.setUser("user");
    sessionFactory.setPassword("pass");

    return sessionFactory;
}

public static void upload() throws IOException {
    SftpSession session = sftpSessionFactory().getSession();
    InputStream fileStream = NumeVersionDownloader.class.getClassLoader().getResourceAsStream("path_to_local_file/test.txt");
    session.write(fileStream, "path_to_remote/test.txt");

    session.close();
}

【讨论】:

    猜你喜欢
    • 2013-11-17
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 2012-03-23
    • 2015-11-09
    • 2016-04-03
    • 2017-02-09
    相关资源
    最近更新 更多