简体   繁体   English

Citrus Framework-使用Spring Integration通过SFTP上传文件

[英]Citrus Framework - upload file via SFTP using Spring Integration

As part of a Citrus test I'd like to push a CSV file to a server via SFTP. 作为Citrus测试的一部分,我想通过SFTP将CSV文件推送到服务器。 It seems this should be possible using Spring Integration. 使用Spring Integration似乎应该可以实现。 I've attempted using the code below: 我尝试使用以下代码:

citrus-config.xml citrus-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:citrus="http://www.citrusframework.org/schema/config"
       xmlns:citrus-test="http://www.citrusframework.org/schema/testcase"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:int="http://www.springframework.org/schema/integration"
       xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/integration/sftp http://www.springframework.org/schema/integration/sftp/spring-integration-sftp.xsd
       http://www.citrusframework.org/schema/config http://www.citrusframework.org/schema/config/citrus-config.xsd
       http://www.citrusframework.org/schema/testcase http://www.citrusframework.org/schema/testcase/citrus-testcase.xsd
">

    <!-- Common settings -->
    <context:property-placeholder location="classpath:citrus.properties"/>

    <citrus:schema-repository id="schemaRepository"/>   

    <!-- SFTP component -->
    <bean id="sftpSessionFactory" class="org.springframework.integration.file.remote.session.CachingSessionFactory">
        <constructor-arg ref="defaultSftpSessionFactory" />
    </bean>

    <bean id="defaultSftpSessionFactory"
          class="org.springframework.integration.sftp.session.DefaultSftpSessionFactory">
        <property name="host" value="${sftp.host}"/>
        <property name="privateKey" value="${sftp.private.keyfile}"/>
        <property name="port" value="${sftp.port}"/>
        <property name="user" value="${sftp.username}"/>
        <property name="allowUnknownKeys" value="true"/>
    </bean>

    <int-sftp:outbound-channel-adapter id="sftpOutboundAdapter"
                                       session-factory="sftpSessionFactory"
                                       channel="inputChannel"
                                       remote-filename-generator-expression="payload.getName()"
                                       remote-directory="/tmp/citrus">
        <int-sftp:request-handler-advice-chain>
            <int:retry-advice />
        </int-sftp:request-handler-advice-chain>
    </int-sftp:outbound-channel-adapter>

    <int:channel id="inputChannel"/>

    <citrus:channel-endpoint id="sftpEndpoint" channel="inputChannel" />
</beans>

SftpTransferIT.java SftpTransferIT.java

public class SftpTransferIT extends TestNGCitrusTestDesigner {

    @Autowired
    ChannelEndpoint sftpEndpoint;

    @Test @Parameters("context")
    @CitrusTest(name = "SftpTransferIT.sendFileByFTP")
    public void sendFileByFTP(@Optional @CitrusResource TestContext context) {

        final File file = new File("C:\\Temp\\example.xml");
        final org.springframework.messaging.Message<File> message = MessageBuilder.withPayload(file).build();
        Message ftpMessage = new ChannelMessageConverter().convertInbound(message,sftpEndpoint.getEndpointConfiguration(),context);

        send(sftpEndpoint).message(ftpMessage);

    }
}

The following exception is thrown in this situation: 在这种情况下,将引发以下异常:

Caused by: org.springframework.messaging.MessagingException: Failed to write to '/tmp/citrus/example.xml.writing' while uploading the file; nested exception is org.springframework.core.NestedIOException: failed to write file; nested exception is 2: No such file
    at org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:537)
    at org.springframework.integration.file.remote.RemoteFileTemplate.lambda$send$0(RemoteFileTemplate.java:310)
    ... 69 more
Caused by: org.springframework.core.NestedIOException: failed to write file; nested exception is 2: No such file
    at org.springframework.integration.sftp.session.SftpSession.write(SftpSession.java:158)
    at org.springframework.integration.file.remote.session.CachingSessionFactory$CachedSession.write(CachingSessionFactory.java:228)
    at org.springframework.integration.file.remote.RemoteFileTemplate.sendFileToRemoteDirectory(RemoteFileTemplate.java:509)
    ... 70 more
Caused by: 2: No such file
    at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2873)

I think the error is in how I'm sending the message via Citrus. 我认为错误在于我如何通过Citrus发送消息。 Can someone please advise on how to send the org.springframework.messaging.Message correctly via Citrus? 有人可以建议如何通过Citrus正确发送org.springframework.messaging.Message吗?

Or is it better practice to use pure Spring Integration without Citrus' send() to perform tasks like this? 还是在不使用Citrus的send()的情况下使用纯Spring Integration执行类似任务的更好实践?

Try to configure use-temporary-file-name = "false" : 尝试配置use-temporary-file-name = "false"

By default, every file that is in the process of being transferred will appear in the file system with an additional suffix which, by default, is .writing; 默认情况下,每个正在传输的文件都会在文件系统中显示,并带有一个附加后缀,默认情况下,后缀为.writing; this can be changed using the temporary-file-suffix attribute. 可以使用临时文件后缀属性更改此设置。

However, there may be situations where you don't want to use this technique (for example, if the server does not permit renaming files). 但是,在某些情况下,您可能不想使用此技术(例如,如果服务器不允许重命名文件)。 For situations like this, you can disable this feature by setting use-temporary-file-name to false (default is true). 在这种情况下,可以通过将use-temporary-file-name设置为false(默认值为true)来禁用此功能。 When this attribute is false, the file is written with its final name and the consuming application will need some other mechanism to detect that the file is completely uploaded before accessing it. 当此属性为false时,将使用文件的最终名称写入文件,并且使用该应用程序的应用程序将需要其他某种机制来检测文件在访问之前已完全上传。

And be sure that /tmp/citrus really exists on your SFTP. 并确保/tmp/citrus确实存在于您的SFTP上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM