【问题标题】:Copy and move a file from SFTP using Java config in Spring Integration在 Spring Integration 中使用 Java 配置从 SFTP 复制和移动文件
【发布时间】:2017-10-18 12:31:22
【问题描述】:

我是 Spring 集成的新手。我有这个要求,首先将文件从 /files 文件夹移动到 SFTP 位置的 /process 文件夹,然后将该文件复制到本地。 建议我使用网关,并且配置必须在 java 中使用注释。 我曾尝试在 stackoverflow 上寻求答案,但找不到相关内容。 但是,我能够使用 @InboundChannelAdapter 并通过配置其他 bean 来复制文件。

下面是我目前写的代码

配置 公共类 SftpConfiguration {

@Value("${ftp.file.host}")
private String host;

@Value("${ftp.file.port")
private int port;

@Value("${ftp.file.user")
private String user;

@Value("${ftp.file.password")
private String password;

@Value("${directorry.file.remote")
private String remoteDir;

@Value("${directorry.file.in.pollerDelay")
final private String pollerDelay = "1000";

@Value("${directory.file.remote.move}")
private String toMoveDirectory;

@Bean
public SessionFactory<LsEntry> sftpSessionFactory() {
    DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
    factory.setHost(host);
    factory.setPort(port);
    factory.setUser(user);
    factory.setPassword(password);
    factory.setAllowUnknownKeys(true);
    return new CachingSessionFactory<LsEntry>(factory);
}

@Bean
public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
    SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
    fileSynchronizer.setDeleteRemoteFiles(false);
    fileSynchronizer.setRemoteDirectory(remoteDir);
    fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xlsx"));
    return fileSynchronizer;
}

@Bean
@InboundChannelAdapter(channel = "sftpChannel", poller = @Poller(fixedDelay = pollerDelay))
public MessageSource<File> sftpMessageSource() {
    SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(
            sftpInboundFileSynchronizer());
    source.setLocalDirectory(new File("ftp-inbound"));
    source.setAutoCreateLocalDirectory(true);
    source.setLocalFilter(new AcceptOnceFileListFilter<File>());

    return source;
}

@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handler() {
    return new MessageHandler() {

        @Override
        public void handleMessage(Message<?> message) throws MessagingException {
            try {
                new FtpOrderRequestHandler().handle((File) message.getPayload());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    };
}

@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler handlerOut() {
    return new SftpOutboundGateway(sftpSessionFactory(), "mv", toMoveDirectory);
}

}

我将不胜感激任何提示或建议。 谢谢。

【问题讨论】:

    标签: java spring spring-integration sftp spring-integration-sftp


    【解决方案1】:

    我试过了,以下对我有用。

    @Configuration
    @EnableIntegration
    public class SftpConfiguration {
    
        @Value("${config.adapter.ftp.host}")
        private String host;
    
        @Value("${config.adapter.ftp.port}")
        private int port;
    
        @Value("${config.adapter.ftp.user}")
        private String user;
    
        @Value("${config.adapter.ftp.password}")
        private String password;
    
        @Autowired
        private FtpOrderRequestHandler handler;
    
        @Autowired
        ConfigurableApplicationContext context;
    
        @Value("${config.adapter.ftp.excel.sourceFolder}")
        private String sourceDir;
    
        @Value("${config.adapter.ftp.excel.localFolder}")
        private String localDir;
    
        @Value("${config.adapter.ftp.excel.backupFolder}")
        private String backupDir;
    
        @Value("${config.adapter.ftp.statusExcel.destinationFolder}")
        private String statusDest;
    
        private static final Logger LOGGER = LoggerFactory.getLogger(SftpConfiguration.class);
    
    
        @Bean
        public SessionFactory<LsEntry> sftpSessionFactory() {
            DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
            factory.setHost(host);
            factory.setPort(port);
            factory.setUser(user);
            factory.setPassword(password);
            factory.setAllowUnknownKeys(true);
            return new CachingSessionFactory<LsEntry>(factory);
        }
    
        @Bean
        public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
            SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
            fileSynchronizer.setDeleteRemoteFiles(true);
            fileSynchronizer.setRemoteDirectory(sourceDir);
            fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter("*.xlsx"));
            return fileSynchronizer;
        }
    
        @Bean
        @InboundChannelAdapter(channel = "sftpChannel", poller = @Poller(cron = "${config.cron.cataligent.order}"), autoStartup = "true")
        public MessageSource<File> sftpMessageSource() {
            SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(
                    sftpInboundFileSynchronizer());
            source.setLocalDirectory(new File(localDir));
            source.setAutoCreateLocalDirectory(true);
            source.setLocalFilter(new AcceptOnceFileListFilter<File>());
            return source;
        }
    
    
        @Bean
        @ServiceActivator(inputChannel = "sftpChannel")
        public MessageHandler handlerOrder() {
            return new MessageHandler() {
                @Override
                public void handleMessage(Message<?> message) throws MessagingException {
                    try {
                        SFTPGateway gateway = context.getBean(SFTPGateway.class);
                        final File orderFile = (File) message.getPayload();
                        gateway.sendToSftp(orderFile);
                        LOGGER.debug("{} is picked by scheduler and moved to {} folder",orderFile.getName(),backupDir);
                        handler.handle((File) message.getPayload());
                        handler.deleteFileFromLocal((File) message.getPayload());
                        LOGGER.info("Processing of file {} is completed",orderFile.getName());
                    } catch (IOException e) {
                        LOGGER.error("Error occurred while processing order file exception is {}",e.getMessage());
                    }
                }
    
            };
        }
    
        @Bean
        @ServiceActivator(inputChannel = "sftpChannelDest")
        public MessageHandler handlerOrderBackUp() {
            SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
            handler.setRemoteDirectoryExpression(new LiteralExpression(backupDir));
            return handler;
        }
    
        @Bean
        @ServiceActivator(inputChannel = "sftpChannelStatus")
        public MessageHandler handlerOrderStatusUS() {
            SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
            handler.setRemoteDirectoryExpression(new LiteralExpression(statusDest));
            return handler;
        }
    
    
    
        @MessagingGateway
        public interface SFTPGateway {
            @Gateway(requestChannel = "sftpChannelDest")
            void sendToSftp(File file);
    
            @Gateway(requestChannel = "sftpChannelStatus")
            void sendToSftpOrderStatus(File file);
    
        }
    
    }
    

    我已使用它从 SFTP 位置获取文件。保存在本地。然后将文件移动到备份文件夹,然后处理整个文件。处理后从本地删除文件。

    我使用网关(@MessagingGateway)进行文件移动,并且在该界面中有两种不同的方法。将同一文件移动到备份文件夹的一种方法是将我的代码中的另一个文件(状态文件)移动到所需的 SFTP 位置。为了更好地理解,我试图保持代码干净。

    【讨论】:

    • 你能帮帮我吗?我每次都收到这个异常 - o.s.integration.handler.LoggingHandler : org.springframework.messaging.MessagingException: 将“/foo”同步到本地目录时出现问题;嵌套异常是 org.springframework.messaging.MessagingException: 无法在会话上执行;嵌套异常是 org.springframework.integration.util.PoolItemNotAvailableException: 无法获取池项
    • @thedevd 我可以知道你想要达到什么目的吗?
    • @NaveenHanda 您能否分享您的 git url 以查看工作示例..
    • @Saravanan 我在我的项目中使用了它,所以它在 git 上不可用,但这是它的精确副本,它仍在工作。如果您需要其他帮助,请告诉我。
    • @NaveenHanda:谢谢 Naveen。我也是 Spring 集成和 Spring Batch 的新手。我只想从 sftp 位置读取文件并将其保存到我的本地驱动器中。你能帮我实现这一点吗..
    【解决方案2】:

    对,您需要使用@Bean@InboundChannelAdapterSftpInboundFileSynchronizingMessageSource 将文件从远程/process 文件夹下载到本地目录。这是在轮询器的基础上完成的,是一个单独的过程,与移动操作完全无关。您可以通过FtpOutboundGateway 使用MV 命令执行该移动逻辑:

    mv 命令没有选项。

    expression 属性定义“from”路径,rename-expression 属性定义“to”路径。 默认情况下,重命名表达式headers['file_renameTo']。 此表达式的计算结果不得为 null 或空的 String。 如有必要,将创建所需的任何远程目录。 结果消息的有效负载是Boolean.TRUEfile_remoteDirectory 标头中提供了原始远程目录,file_remoteFile 标头中提供了文件名。 新路径位于 file_renameTo 标头中。

    这个你必须通过:

    @Bean
    @ServiceActivator(inputChannel = "sftpChannel")
    public MessageHandler handler() {
        return new SftpOutboundGateway(ftpSessionFactory(), "mv", "'my_remote_dir/my_file'");
    }
    

    【讨论】:

    • Artem Bilan 我明白你的意思了。因此,您建议使用 SftpOutboundGateway 将我的文件从 /files 文件夹移动到 /process 文件夹。我的查询是首先我们使用@InboundChannelAdapter 从/file 中选择文件,然后SftpOutboundGateway 将其移动到所需的位置,例如/process。现在我想将该文件从 /process 复制到本地。这将如何发生。我正在将迄今为止编写的代码添加到我的问题中。请查看并建议我应该进行哪些更改才能将移动的文件从 /process 复制到本地。
    • 到目前为止,我在您的代码中没有发现问题。但是,如果您谈论本地/files 目录,那么是的,您必须使用FileReadingMessageSource 并将这些本地文件通过SftpMessageHandler 发送到远程/process。另一方面,您绝对可以继续使用SftpInboundFileSynchronizingMessageSource 将远程文件从/process 轮询到本地目录。否则,请重新表述您的要求,并将其视为我的评论,因为我只是不理解这项任务
    • 嗨,artem 让我再次尝试解释一下。假设您在 sftp 上有两个名为 /initial 和 /final 的文件夹,一个位于本地调用者 /local 的文件夹。现在的要求是首先将文件从 /initial 移动到 /final。然后将该文件从 /final 复制到 /local。我希望这可以帮助您更好地理解问题。现在要求到位你认为上面的代码是正确的。
    • 好吧,那么不:你使用 sftpChannel 错误的方式。 1.你必须使用MV命令SftpOutboundGateway从一个远程冷杉到另一个远程文件。您应该发送文件名以移入此网关。 SftpIbboundFileSynchronizingMessageSource 应该查看目标远程目录,它会将远程文件同步到本地目录,同时生成消息。
    • 非常感谢@Artem。你能告诉我如何将源文件名传递给网关吗??
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多