如何使用sftp和spring boot将文件从ftp服务器复制到本地目录

时间:2019-10-17 00:01:13

标签: spring-boot sftp

我有用于SFTP的入站和出站通道适配器的代码。我想通过Spring Boot Scheduler调用那些方法而不使用轮询。寻找例如如何调用resultFileHandler()方法

public class SftpConfig {
    @Value("${nodephone.directory.sftp.host}")
    private String sftpHost;
    @Value("${nodephone.directory.sftp.port}")
    private int sftpPort;
    @Value("${nodephone.directory.sftp.user}")
    private String sftpUser;
    @Value("${nodephone.directory.sftp.password}")
    private String sftpPasword;
    @Value("${nodephone.directory.sftp.remote.directory.download}")
    private String sftpRemoteDirectoryDownload;
    @Value("${nodephone.directory.sftp.remote.directory.upload}")
    private String sftpRemoteDirectoryUpload;
    @Value("${nodephone.directory.sftp.remote.directory.filter}")
    private String sftpRemoteDirectoryFilter;
    @Value("${nodephone.directory.sftp.remote.directory.localDirectory}")
    private String sftpLocalDirectory;

    // private FtpOrderRequestHandler handler;

    @Bean
    public SessionFactory<LsEntry> sftpSessionFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
        factory.setHost(sftpHost);
        factory.setPort(sftpPort);
        factory.setUser(sftpUser);
        factory.setPassword(sftpPasword);
        factory.setAllowUnknownKeys(true);
        return new CachingSessionFactory<LsEntry>(factory);
    }

    @Bean
    public SftpInboundFileSynchronizer sftpInboundFileSynchronizer() {
        SftpInboundFileSynchronizer fileSynchronizer = new SftpInboundFileSynchronizer(sftpSessionFactory());
        fileSynchronizer.setDeleteRemoteFiles(true);
        fileSynchronizer.setRemoteDirectory(sftpRemoteDirectoryDownload);
        fileSynchronizer.setFilter(new SftpSimplePatternFileListFilter(sftpRemoteDirectoryFilter));
        return fileSynchronizer;
    }

    @Bean
    @InboundChannelAdapter(channel = "fromSftpChannel", poller = @Poller(cron = "0/5 * * * * *"))
    public MessageSource<File> sftpMessageSource() {
        SftpInboundFileSynchronizingMessageSource source = new SftpInboundFileSynchronizingMessageSource(
                sftpInboundFileSynchronizer());
        source.setAutoCreateLocalDirectory(true);
        source.setLocalFilter(new AcceptOnceFileListFilter<File>());
        source.setLocalDirectory(new File("/local"));
        return source;
    }

    @Bean
    @ServiceActivator(inputChannel = "fromSftpChannel")
    public MessageHandler resultFileHandler() {
        return new MessageHandler() {
            @Override
            public void handleMessage(Message<?> message) throws MessagingException {

                System.out.println("********************** " + message.getPayload());

            }
        };
    }

我已经使用Configuration批注进行了测试,它从服务器读取了文件,但是我想从Cron而不是通过轮询运行它,如何调用方法resultFileHandler()

1 个答案:

答案 0 :(得分:0)

我从来没有在任何生产代码中使用Spring Integration来做到这一点,尽管我做了以下类似的事情来使用sftp / ftp从远程服务器下载文件。

我仅使用SftpOutboundGateway(可能有更好的方法)来调用“ mget” 方法并获取有效负载(文件)。

@Configuration
@ConfigurationProperties(prefix = "sftp")
@Setter
@Getter
@EnableIntegration
public class RemoteFileConfiguration {

  private String clients;
  private String hosts;
  private int ports;
  private String users;
  private String passwords;


  @Bean(name = "clientSessionFactory")
  public SessionFactory<LsEntry> clientSessionFactory() {
    DefaultSftpSessionFactory sf = new DefaultSftpSessionFactory();
    sf.setHost(hosts);
    sf.setPort(ports);
    sf.setUser(users);
    sf.setPassword(passwords);
    sf.setAllowUnknownKeys(true);
    return new CachingSessionFactory<>(sf);
  }

  @Bean
  @ServiceActivator(inputChannel = "sftpChannel")
  public MessageHandler clientMessageHandler() {

    SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(
        clientSessionFactory(), "mget", "payload");
    sftpOutboundGateway.setAutoCreateLocalDirectory(true);
    sftpOutboundGateway.setLocalDirectory(new File("/users/localPath/client/INPUT/"));
    sftpOutboundGateway.setFileExistsMode(FileExistsMode.REPLACE_IF_MODIFIED);
    sftpOutboundGateway.setFilter(new AcceptOnceFileListFilter<>());
    return sftpOutboundGateway;
  }

}
@MessagingGateway
public interface SFTPGateway {

  @Gateway(requestChannel = "sftpChannel")
  List<File> get(String dir);

}

为了确保我们使用cron来执行此操作,我在需要使用cron表达式时使用了Spring Batch执行的Tasklet。

@Slf4j
@Getter
@Setter
public class RemoteFileInboundTasklet implements Tasklet {

  private RemoteFileTemplate remoteFileTemplate;
  private String remoteClientDir;
  private String clientName;

  private SFTPGateway sftpGateway;

  @Override
  public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext)
      throws Exception {

    List<File> files = sftpGateway.get(remoteClientDir);

    if (CollectionUtils.isEmpty(files)) {
      log.warn("No file was downloaded for client {}.", clientName);
      return RepeatStatus.FINISHED;
    }

    log.info("Total file: {}", files.size());
    return RepeatStatus.FINISHED;
  }

}

注意::如果您不想使用Batch的Tasklet,则可以使用@Component类并注入网关以调用“ get”方法。

@Autowired
private SFTPGateway sftpGateway;