英文:
Spring Integration SFTP (xml) Outbound Gateway - copy folderstructure from remote directory to local directory using SPEL Expression and java
问题
我是完全新手,对于Spring Integration和Spring都不太了解。能够将文件递归复制到本地文件夹已经是个奇迹,但我已经可以做到了,我是基于Spring的这个示例应用程序构建的:
现在我想保持与远程文件夹相同的子目录结构。
我使用的是Spring 4.1.9 Release版本,因为有遗留代码。以下是我的依赖项:
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-sftp</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
</dependencies>
这是一个包含main方法的简单App类,用于加载应用程序上下文:
@Component
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:SftpOutboundGateway-context-test.xml");
ToSftpFlowGateway toFtpFlow = ctx.getBean(ToSftpFlowGateway.class);
toFtpFlow.lsGetAndRmFiles("/remote_directory/");
}
}
这是接口,bean是在xml配置文件中创建的:
public interface ToSftpFlowGateway {
List<Boolean> lsGetAndRmFiles(String dir);
}
这是xml spring配置文件。它引用了web.xml,在那里创建了sessionfactory。在这里,我使用了outbound-gateway:
<?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:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/sftp
https://www.springframework.org/schema/integration/sftp/spring-integration-sftp-4.1.xsd">
<import resource="web.xml"/>
<int:gateway id="gw"
service-interface="ToSftpFlowGateway"
default-request-channel="receiveChannel"
/>
<int-sftp:outbound-gateway id="gateway1"
auto-startup="true"
session-factory="sftpSessionFactory"
request-channel="receiveChannel"
command="mget"
local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"
auto-create-local-directory="true"
rename-expression=""
command-options="-R"
mode="IGNORE"
expression="payload"
reply-channel="loggingChannel"
>
<int:poller fixed-rate="1"/>
</int-sftp:outbound-gateway>
<int:channel id="receiveChannel">
<int:queue/>
</int:channel>
<int:logging-channel-adapter id="loggingChannel" log-full-message="true" logger-name="tapInbound"
level="INFO" />
</beans>
我想知道为什么我的子目录为空。我希望我的子目录是C:/temp/in和C:/temp/out,就像下面的图片一样:
现在,我得到以下作为日志的输出:
INFO: GenericMessage [payload=[C:\temp\null\file.txt, C:\temp\null\file2.txt, C:\temp\null\file3.txt], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, id=f012840c-184e-203e-1a90-754beb8796d1, file_remoteDirectory=/remote_directory/, file_remoteFile=, timestamp=1684943419215}]
这里可能是有问题的地方:
local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"
Spring文档中提到以下内容,但我不太明白:
通常,您会在local-directory-expression中使用#remoteDirectory变量,以便保留本地目录结构。
英文:
I am totally new to Spring Integration and a beginner in Spring. It is a miracle that I got so far but I already can copy my files recursively into a local folder. I based my app on this sample application from Spring:
Now I want to keep the same subdirectories as in the remote folder.
I am using Spring 4.1.9 Release, because of legacy code. These are my dependencies.
<dependencies>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-sftp</artifactId>
<version>4.1.9.RELEASE</version>
</dependency>
</dependencies>
This is a simple App class with main method which loads the applicationcontext.
@Component
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
"classpath:SftpOutboundGateway-context-test.xml");
ToSftpFlowGateway toFtpFlow = ctx.getBean(ToSftpFlowGateway.class);
toFtpFlow.lsGetAndRmFiles("/remote_directory/");
}
}
This is the interface, and the bean is made in the xml config underneath
public interface ToSftpFlowGateway
{
List<Boolean> lsGetAndRmFiles(String dir);
}
This is the xml spring config. It has a reference to web.xml where the sessionfactory is made. Here I use the outbound-gateway
<?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:int="http://www.springframework.org/schema/integration"
xmlns:int-sftp="http://www.springframework.org/schema/integration/sftp"
xsi:schemaLocation="http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-4.1.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration/sftp
https://www.springframework.org/schema/integration/sftp/spring-integration-sftp-4.1.xsd">
<import resource="web.xml"/>
<int:gateway id="gw"
service-interface="ToSftpFlowGateway"
default-request-channel="receiveChannel"
/>
<int-sftp:outbound-gateway id="gateway1"
auto-startup="true"
session-factory="sftpSessionFactory"
request-channel="receiveChannel"
command="mget"
local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"
auto-create-local-directory="true"
rename-expression=""
command-options="-R"
mode="IGNORE"
expression="payload"
reply-channel="loggingChannel"
>
<int:poller fixed-rate="1"/>
</int-sftp:outbound-gateway>
<int:channel id="receiveChannel">
<int:queue/>
</int:channel>
<int:logging-channel-adapter id="loggingChannel" log-full-message="true" logger-name="tapInbound"
level="INFO" />
</beans>
I want to know why my subdirectories are null. I want my subdirectories to be C:/temp/in and C:/temp/out as the following picture.
Now i get the following output as logging:
INFO: GenericMessage [payload=[C:\temp\null\file.txt, C:\temp\null\file2.txt, C:\temp\null\file3.txt], headers={replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@534a53da, id=f012840c-184e-203e-1a90-754beb8796d1, file_remoteDirectory=/remote_directory/, file_remoteFile=, timestamp=1684943419215}]
This is probably wrong
local-directory-expression="'C:/temp/' + headers['file_remoteDirectory']"
Spring documentation says the following, but I don't understand:
> Typically, you would use the #remoteDirectory variable in the
> local-directory-expression so that the remote directory structure is
> retained locally.
答案1
得分: 1
The headers['file_remoteDirectory']
表达式引用了请求消息,该消息显然没有该信息,因为它只是一个简单的消息:
toFtpFlow.lsGetAndRmFiles("/remote_directory/");
尝试将你的 local-directory-expression
修改为:
local-directory-expression="'C:/temp/' + #remoteDirectory"
其中 remoteDirectory
SpEL 变量被填充为每个检索到的文件的远程子目录的路径:
private File generateLocalDirectory(Message<?> message, String remoteDirectory) {
EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
if (remoteDirectory != null) {
evaluationContext.setVariable("remoteDirectory", remoteDirectory);
}
File localDir = ExpressionUtils.expressionToFile(this.localDirectoryExpression, evaluationContext, message, "Local Directory");
if (!localDir.exists()) {
Assert.isTrue(localDir.mkdirs(), () -> "Failed to make local directory: " + localDir);
}
return localDir;
}
英文:
The headers['file_remoteDirectory']
expression references to the request message which is definitely doesn't have that info because it is a plain message:
toFtpFlow.lsGetAndRmFiles("/remote_directory/");
Try to modify your local-directory-expression
to this:
local-directory-expression="'C:/temp/' + #remoteDirectory"
Where that remoteDirectory
SpEL variable is populated for the path of the remote sub-dir against every file retrieved:
private File generateLocalDirectory(Message<?> message, String remoteDirectory) {
EvaluationContext evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
if (remoteDirectory != null) {
evaluationContext.setVariable("remoteDirectory", remoteDirectory);
}
File localDir = ExpressionUtils.expressionToFile(this.localDirectoryExpression, evaluationContext, message,
"Local Directory");
if (!localDir.exists()) {
Assert.isTrue(localDir.mkdirs(), () -> "Failed to make local directory: " + localDir);
}
return localDir;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论