Spring Boot 使用Spring Integration Sftp上载文件时无法写入文件

2ic8powd  于 2022-11-05  发布在  Spring
关注(0)|答案(1)|浏览(211)

我已经尝试使用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"

我的项目基于Sping Boot 2.7.4/Kotlin协同程序/Java 17。
我已经定义了以下用于上传的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以产生问题。

f0ofjuux

f0ofjuux1#

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

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 = YourClassName.class.getClassLoader().getResourceAsStream("path_to_local_file/test.txt");
    session.write(fileStream, "path_to_remote/test.txt");

    session.close();
}

相关问题