This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 5c9093a9845 NIFI-16159 Add support for FileResourceService in PutFile
(#11495)
5c9093a9845 is described below
commit 5c9093a9845329a5886289e8620953dbcc2d43a9
Author: Shubham Sharma <[email protected]>
AuthorDate: Sat Aug 29 22:45:06 2026 -0400
NIFI-16159 Add support for FileResourceService in PutFile (#11495)
Signed-off-by: David Handermann <[email protected]>
---
.../nifi-standard-processors/pom.xml | 15 +++++++++
.../apache/nifi/processors/standard/PutFile.java | 23 +++++++++++--
.../nifi/processors/standard/TestPutFile.java | 38 ++++++++++++++++++++++
3 files changed, 74 insertions(+), 2 deletions(-)
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
index d78dfb58a5f..2414455b7bb 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/pom.xml
@@ -38,6 +38,21 @@
<artifactId>nifi-standard-record-utils</artifactId>
<version>2.12.0-SNAPSHOT</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-resource-transfer</artifactId>
+ <version>2.12.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-file-resource-service-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-file-resource-service</artifactId>
+ <version>2.12.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
index db820f89ed3..5a9fe712f2f 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/PutFile.java
@@ -27,6 +27,7 @@ import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.ValidationResult;
import org.apache.nifi.components.Validator;
import org.apache.nifi.expression.ExpressionLanguageScope;
+import org.apache.nifi.fileresource.service.api.FileResource;
import org.apache.nifi.flowfile.FlowFile;
import org.apache.nifi.flowfile.attributes.CoreAttributes;
import org.apache.nifi.logging.ComponentLog;
@@ -36,11 +37,14 @@ import org.apache.nifi.processor.ProcessSession;
import org.apache.nifi.processor.Relationship;
import org.apache.nifi.processor.exception.ProcessException;
import org.apache.nifi.processor.util.StandardValidators;
+import org.apache.nifi.processors.transfer.ResourceTransferSource;
import org.apache.nifi.util.StopWatch;
+import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFilePermissions;
import java.nio.file.attribute.UserPrincipalLookupService;
@@ -48,11 +52,16 @@ import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
+import java.util.Optional;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import static
org.apache.nifi.processors.transfer.ResourceTransferProperties.FILE_RESOURCE_SERVICE;
+import static
org.apache.nifi.processors.transfer.ResourceTransferProperties.RESOURCE_TRANSFER_SOURCE;
+import static
org.apache.nifi.processors.transfer.ResourceTransferUtils.getFileResource;
+
@SupportsBatching
@InputRequirement(Requirement.INPUT_REQUIRED)
@Tags({"put", "local", "copy", "archive", "files", "filesystem"})
@@ -158,7 +167,9 @@ public class PutFile extends AbstractProcessor {
CHANGE_LAST_MODIFIED_TIME,
CHANGE_PERMISSIONS,
CHANGE_OWNER,
- CHANGE_GROUP
+ CHANGE_GROUP,
+ RESOURCE_TRANSFER_SOURCE,
+ FILE_RESOURCE_SERVICE
);
public static final int MAX_FILE_LOCK_ATTEMPTS = 10;
@@ -304,7 +315,15 @@ public class PutFile extends AbstractProcessor {
}
}
- session.exportTo(flowFile, dotCopyFile, false);
+ final ResourceTransferSource resourceTransferSource =
context.getProperty(RESOURCE_TRANSFER_SOURCE).asAllowableValue(ResourceTransferSource.class);
+ final Optional<FileResource> fileResource =
getFileResource(resourceTransferSource, context, flowFile.getAttributes());
+ if (fileResource.isPresent()) {
+ try (InputStream in = fileResource.get().getInputStream()) {
+ Files.copy(in, dotCopyFile,
StandardCopyOption.REPLACE_EXISTING);
+ }
+ } else {
+ session.exportTo(flowFile, dotCopyFile, false);
+ }
final String lastModifiedTime =
context.getProperty(CHANGE_LAST_MODIFIED_TIME).evaluateAttributeExpressions(flowFile).getValue();
if (lastModifiedTime != null && !lastModifiedTime.isBlank()) {
diff --git
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutFile.java
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutFile.java
index 6afa8c97fe7..7781eae8ef4 100644
---
a/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutFile.java
+++
b/nifi-extension-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestPutFile.java
@@ -16,7 +16,11 @@
*/
package org.apache.nifi.processors.standard;
+import org.apache.nifi.fileresource.service.StandardFileResourceService;
+import org.apache.nifi.fileresource.service.api.FileResourceService;
import org.apache.nifi.flowfile.attributes.CoreAttributes;
+import org.apache.nifi.processors.transfer.ResourceTransferProperties;
+import org.apache.nifi.processors.transfer.ResourceTransferSource;
import org.apache.nifi.util.TestRunner;
import org.apache.nifi.util.TestRunners;
import org.junit.jupiter.api.AfterEach;
@@ -24,9 +28,11 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
import java.io.File;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.FileVisitResult;
import java.nio.file.FileVisitor;
import java.nio.file.Files;
@@ -244,6 +250,38 @@ public class TestPutFile {
assertEquals("Another file", new String(content));
}
+ @Test
+ public void testPutFileFromLocalFile(@TempDir final Path sourceDir) throws
Exception {
+ final TestRunner runner = TestRunners.newTestRunner(new PutFile());
+ runner.setProperty(PutFile.DIRECTORY, targetDir.getAbsolutePath());
+ runner.setProperty(PutFile.CONFLICT_RESOLUTION,
PutFile.REPLACE_RESOLUTION);
+
+ final String attributeName = "file.path";
+ final String serviceId = FileResourceService.class.getSimpleName();
+ final FileResourceService service = new StandardFileResourceService();
+ runner.addControllerService(serviceId, service);
+ runner.setProperty(service, StandardFileResourceService.FILE_PATH,
String.format("${%s}", attributeName));
+ runner.enableControllerService(service);
+
+
runner.setProperty(ResourceTransferProperties.RESOURCE_TRANSFER_SOURCE,
ResourceTransferSource.FILE_RESOURCE_SERVICE.getValue());
+ runner.setProperty(ResourceTransferProperties.FILE_RESOURCE_SERVICE,
serviceId);
+
+ final byte[] fileData = "0123456789".getBytes(StandardCharsets.UTF_8);
+ final Path sourceFilePath = sourceDir.resolve("source.txt");
+ Files.write(sourceFilePath, fileData);
+
+ final Map<String, String> attributes = new HashMap<>();
+ attributes.put(CoreAttributes.FILENAME.key(), "targetFile.txt");
+ attributes.put(attributeName, sourceFilePath.toString());
+ runner.enqueue(new byte[0], attributes);
+ runner.run();
+
+ runner.assertAllFlowFilesTransferred(PutFile.REL_SUCCESS, 1);
+ final Path targetPath = Paths.get(TARGET_DIRECTORY +
"/targetFile.txt");
+ final byte[] content = Files.readAllBytes(targetPath);
+ assertEquals("0123456789", new String(content,
StandardCharsets.UTF_8));
+ }
+
private TestRunner putFileRunner;
private final String testFile = "src" + File.separator + "test" +
File.separator + "resources" + File.separator + "hello.txt";