From 56708b448c1e90ae3ad114bb1821752f3b63ce81 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Fri, 3 Mar 2017 15:46:35 -0500 Subject: [PATCH] INT-3746: (S)FTP outbound: support `InputStream` JIRA: https://jira.spring.io/browse/INT-3746 --- .../file/remote/RemoteFileTemplate.java | 7 ++-- .../integration/ftp/dsl/FtpTests.java | 34 +++++++++++-------- src/reference/asciidoc/whats-new.adoc | 2 ++ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java index dcc0a12cba..8bf8afeb51 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/RemoteFileTemplate.java @@ -443,7 +443,10 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ Object payload = message.getPayload(); InputStream dataInputStream = null; String name = null; - if (payload instanceof File) { + if (payload instanceof InputStream) { + dataInputStream = (InputStream) payload; + } + else if (payload instanceof File) { File inputFile = (File) payload; if (inputFile.exists()) { dataInputStream = new BufferedInputStream(new FileInputStream(inputFile)); @@ -464,7 +467,7 @@ public class RemoteFileTemplate implements RemoteFileOperations, Initializ } else { throw new IllegalArgumentException("Unsupported payload type. The only supported payloads are " + - "java.io.File, java.lang.String, and byte[]"); + "java.io.File, java.lang.String, byte[] and InputStream"); } if (dataInputStream == null) { return null; diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/dsl/FtpTests.java b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/dsl/FtpTests.java index 08a12d5d9c..6e3755fae1 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/dsl/FtpTests.java +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/dsl/FtpTests.java @@ -24,8 +24,10 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.regex.Matcher; @@ -79,8 +81,8 @@ public class FtpTests extends FtpTestSupport { .localFilename(f -> f.toUpperCase() + ".a") .localDirectory(getTargetLocalDirectory()), e -> e.id("ftpInboundAdapter").poller(Pollers.fixedDelay(100))) - .channel(out) - .get(); + .channel(out) + .get(); IntegrationFlowRegistration registration = this.flowContext.registration(flow).register(); Message message = out.receive(10_000); assertNotNull(message); @@ -119,8 +121,8 @@ public class FtpTests extends FtpTestSupport { .remoteDirectory("ftpSource") .regexFilter(".*\\.txt$"), e -> e.id("ftpInboundAdapter").poller(Pollers.fixedDelay(100))) - .channel(out) - .get(); + .channel(out) + .get(); IntegrationFlowRegistration registration = this.flowContext.registration(flow).register(); Message message = out.receive(10_000); assertNotNull(message); @@ -140,15 +142,17 @@ public class FtpTests extends FtpTestSupport { @Test public void testFtpOutboundFlow() { IntegrationFlow flow = f -> f - .handle(Ftp.outboundAdapter(sessionFactory(), FileExistsMode.FAIL) - .useTemporaryFileName(false) - .fileNameExpression("headers['" + FileHeaders.FILENAME + "']") - .remoteDirectory("ftpTarget")); + .handle(Ftp.outboundAdapter(sessionFactory(), FileExistsMode.FAIL) + .useTemporaryFileName(false) + .fileNameExpression("headers['" + FileHeaders.FILENAME + "']") + .remoteDirectory("ftpTarget")); IntegrationFlowRegistration registration = this.flowContext.registration(flow).register(); String fileName = "foo.file"; - registration.getInputChannel().send(MessageBuilder.withPayload("foo") - .setHeader(FileHeaders.FILENAME, fileName) - .build()); + Message message = MessageBuilder + .withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8))) + .setHeader(FileHeaders.FILENAME, fileName) + .build(); + registration.getInputChannel().send(message); RemoteFileTemplate template = new RemoteFileTemplate<>(sessionFactory()); FTPFile[] files = template.execute(session -> session.list(getTargetRemoteDirectory().getName() + "/" + fileName)); @@ -165,10 +169,10 @@ public class FtpTests extends FtpTestSupport { IntegrationFlow flow = f -> f .handle(Ftp.outboundGateway(sessionFactory(), AbstractRemoteFileOutboundGateway.Command.MGET, "payload") - .options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE) - .filterExpression("name matches 'subFtpSource|.*1.txt'") - .localDirectoryExpression("'" + getTargetLocalDirectoryName() + "' + #remoteDirectory") - .localFilenameExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')")) + .options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE) + .filterExpression("name matches 'subFtpSource|.*1.txt'") + .localDirectoryExpression("'" + getTargetLocalDirectoryName() + "' + #remoteDirectory") + .localFilenameExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')")) .channel(out); IntegrationFlowRegistration registration = this.flowContext.registration(flow).register(); String dir = "ftpSource/"; diff --git a/src/reference/asciidoc/whats-new.adoc b/src/reference/asciidoc/whats-new.adoc index 156ff04670..a08edec72a 100644 --- a/src/reference/asciidoc/whats-new.adoc +++ b/src/reference/asciidoc/whats-new.adoc @@ -99,6 +99,8 @@ See <> and <> for more information. The (S)FTP streaming inbound channel adapters now add remote file information in a message header. See <> and <> for more information. +The FTP and SFTP outbound channel adapters, as well as `PUT` command of the outbound gateways, now support `InputStream` as `payload`, too. + ==== Integration Properties Since _version 4.3.2_ a new `spring.integration.readOnly.headers` global property has been added to customize the list of headers which should not be copied to a newly created `Message` by the `MessageBuilder`.