【问题标题】:What's the procedure to re-download locally deleted files using SFTP Inbound使用 SFTP Inbound 重新下载本地删除的文件的程序是什么
【发布时间】:2020-05-28 19:41:41
【问题描述】:

据此 doc 找不到从远程 SFTP 重新下载本地删除文件的正确进程。

要求是,删除已经从远程 SFTP 获取的本地文件,并在需要时使用 sftp-inbound-adapter (DSL configuration) 重新获取相同的文件。在这个实现中,MetadataStore 没有被持久化到任何外部系统,如 PropertiesPersistingMetadataStoreRedis 元数据存储。所以根据 docMetadataStore 存储在 In-Memory 中。

找不到任何方法从MetadataStore 中删除该远程文件的元数据,以便使用file_name 重新获取本地删除的文件。而且一点头绪都没有,这个removeRemoteFileMetadata()回调需要怎么实现(according to this doc)。

配置类包含以下内容:

    @Bean
    public IntegrationFlow fileFlow() {
        SftpInboundChannelAdapterSpec spec = Sftp.inboundAdapter(sftpConfig.getSftpSessionFactory())
                .preserveTimestamp(true)
                .patternFilter(Constants.FILE_NAME_CONVENTION)
                .remoteDirectory(sftpConfig.getSourceLocation())
                .autoCreateLocalDirectory(true)
                .deleteRemoteFiles(false)
                .localDirectory(new File(sftpConfig.getDestinationLocation()));

        return IntegrationFlows
                .from(spec, e -> e.id("sftpInboundAdapter").autoStartup(false)
                        .poller(Pollers.fixedDelay(5000).get()))
                .channel(MessageChannels.direct().get())
                .handle(message -> {
                    log.info("Fetching File : " + message.getHeaders().get("file_name").toString());
                })
                .get();
    }

【问题讨论】:

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


    【解决方案1】:

    我试图解决这个问题,我使用了Tanvir Hossain 的参考代码。我是这样编码的。

    @Bean
    public IntegrationFlow fileFlow() {
        SftpInboundChannelAdapterSpec spec = Sftp
                .inboundAdapter(sftpConfig.getSftpSessionFactory())
                .preserveTimestamp(true)
                .filter(sftpFileListFilter())
                .localFilter(systemFileListFilter())
                .remoteDirectory(sftpConfig.getSourceLocation())
                .autoCreateLocalDirectory(true)
                .deleteRemoteFiles(false)
                .localDirectory(new File(sftpConfig.getDestinationLocation()));
    
        return IntegrationFlows
                .from(spec, e -> e.id("sftpInboundAdapter").autoStartup(false)
                        .poller(Pollers.fixedDelay(5000).get()))
                .channel(MessageChannels.direct().get())
                .handle(message -> {
                    log.info("Fetching File : " 
                            + message.getHeaders().get("file_name").toString());
                })
                .get();
    }
    
    
    private FileSystemPersistentAcceptOnceFileListFilter systemFileListFilter() {
    
        return new FileSystemPersistentAcceptOnceFileListFilter(store(), prefix);
    }
    
    
    private ChainFileListFilter<ChannelSftp.LsEntry> sftpFileListFilter() {
    
        ChainFileListFilter<ChannelSftp.LsEntry> chainFileListFilter = 
                                                    new ChainFileListFilter<>();
        chainFileListFilter.addFilters(
                new SftpPersistentAcceptOnceFileListFilter(store(), prefix),
                new SftpSimplePatternFileListFilter(sftpConfig.getFileFilterValue())
        );
        return chainFileListFilter;
    }
    
    @Bean
    public SimpleMetadataStore store() {
        return new SimpleMetadataStore();
    }
    

    我用于删除元数据的Controller 如下所示:

    public class Controller { 
    
        private final SimpleMetadataStore simpleMetadataStore;
    
        public Controller(SimpleMetadataStore simpleMetadataStore) {
    
               this.simpleMetadataStore = simpleMetadataStore;
    
        }
    
        @GetMapping("/test/remove-metadata/{type}/{fileName}")
        @ResponseBody
        public String removeFileMetadata(
                 @PathVariable("fileName") String fileName,
                 @PathVariable("type") String type
        ) {
            String prefix = definedPrefix;
            String filePath = "";
            if(type.equals("local")){
                filePath = "/local/storage/path/" + fileName;
            }else if(type.equals("remote")){
                filePath = fileName
            }
            String key = prefix + filePath;
    
            simpleMetadataStore.remove(key);
            return key;
        }
    
    }
    

    我正在获取我想要的文件。它正在为我重新获取文件。

    【讨论】:

    • 谢谢,我错误地添加了SftpPersistentAcceptOnceFileListFilter 过滤器和SftpSimplePatternFileListFilter。这很有帮助。
    • 但是在你的控制器中,你使用了一个类型来选择绝对路径或者只是文件名。哪一个对你有用?
    • 我添加这些是为了测试。但是 remote 类型对我有用。
    【解决方案2】:

    使用ChainFileListFilterSftpSimplePatternFileListFilterSftpPersistentAcceptOnceFileListFilter

    使用SimpleMetadataStore 将状态存储在内存中(或其他一些MetadataStore)。

    new SftpPersistentAcceptOnceFileListFilter(store, "somePrefix");

    那么,store.remove(key) 其中keysomePrefix + fileName

    localFilterFileSystemPersistentAcceptOnceFileListFilter 中使用类似的过滤器。

    【讨论】:

    • 我需要像这样创建一个SimpleMetadataStore bean 吗? @Bean public SimpleMetadataStore store() { return new SimpleMetadataStore(); }
    • 我应该使用远程文件还是本地文件的绝对路径或者只需 文件名 即可构造 key?
    • 对于 sftp 过滤器,它是远程文件名;对于文件系统过滤器,它是绝对路径。请参阅每个过滤器中的 fileName() 方法。它是从抽象类中的buildKey() 调用的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2015-06-16
    • 2016-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多