From ea3e118c8cbc784c163888e4173220d7ed58abfc Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 12 Oct 2023 09:46:06 -0400 Subject: [PATCH] Remove request FILENAME header for MPUT (#8761) Related to: https://stackoverflow.com/questions/77268009/how-to-use-sftp-spring-integration-mput-with-sftpoutboundgateway-when-file-objec In some scenarios when the flow starts with a file inbound channel adapter and then an MPUT operation is performed for remote file outbound gateway, the populated in the beginning `FileHeaders.FILENAME` is used from the `DefaultFileNameGenerator` for all the files from local directory to upload. Such a behaviour leads only to the last file in the target remote directory and only with the name from that header. * Fix the `AbstractRemoteFileOutboundGateway` to remove a `FileHeaders.FILENAME` header when message is build for specific item from MPUT request. This way an original local file is used when we upload directory. --- .../AbstractRemoteFileOutboundGateway.java | 15 ++++++++++++--- .../ftp/outbound/FtpServerOutboundTests.java | 8 +++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java index bf28676d09..385a98492e 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/gateway/AbstractRemoteFileOutboundGateway.java @@ -55,12 +55,13 @@ import org.springframework.integration.handler.AbstractReplyProducingMessageHand import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor; import org.springframework.integration.handler.MessageProcessor; import org.springframework.integration.support.AbstractIntegrationMessageBuilder; -import org.springframework.integration.support.MutableMessage; +import org.springframework.integration.support.MutableMessageBuilder; import org.springframework.integration.support.PartialSuccessException; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandlingException; +import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; @@ -867,7 +868,8 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply } if (payload instanceof Collection files) { return files.stream() - .map(p -> doMput(new MutableMessage<>(p, requestMessage.getHeaders()))) + .map((filePayload) -> mputItemMessage(filePayload, requestMessage.getHeaders())) + .map(this::doMput) .collect(Collectors.toList()); } else if (!file.isDirectory()) { @@ -879,6 +881,13 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply } } + private static Message mputItemMessage(Object payload, MessageHeaders requestHeaders) { + return MutableMessageBuilder.withPayload(payload) + .copyHeaders(requestHeaders) + .removeHeader(FileHeaders.FILENAME) + .build(); + } + /** * Put files from the provided directory to the remote server recursively. * The message can be consulted to determine some context. @@ -899,7 +908,7 @@ public abstract class AbstractRemoteFileOutboundGateway extends AbstractReply try { for (File filteredFile : filteredFiles) { if (!filteredFile.isDirectory()) { - String path = doPut(new MutableMessage<>(filteredFile, requestMessage.getHeaders()), subDirectory); + String path = doPut(mputItemMessage(filteredFile, requestMessage.getHeaders()), subDirectory); if (path != null) { replies.add(path); } diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java index 7a1db935b0..4b79754ead 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java @@ -398,7 +398,13 @@ public class FtpServerOutboundTests extends FtpTestSupport { session = TestUtils.getPropertyValue(session, "targetSession", Session.class); FTPClient client = spy(TestUtils.getPropertyValue(session, "client", FTPClient.class)); new DirectFieldAccessor(session).setPropertyValue("client", client); - this.inboundMPut.send(new GenericMessage<>(getSourceLocalDirectory())); + // The FileHeaders.FILENAME is removed by the AbstractRemoteFileOutboundGateway + // when MPUT item is prepared for its specific PUT + Message mputRequestMessage = + MessageBuilder.withPayload(getSourceLocalDirectory()) + .setHeader(FileHeaders.FILENAME, "inbound_file_name") + .build(); + this.inboundMPut.send(mputRequestMessage); @SuppressWarnings("unchecked") Message> out = (Message>) this.output.receive(1000); assertThat(out).isNotNull();