Bläddra i källkod

Add configurable file source input to OCR Upload node

- Add fileSource config field to specify file input via expression
- Supports expressions like {{item.attachments[0]}} for loop iterations
- Falls back to auto-detection from input if fileSource not configured
- Handles both single file objects and arrays (uses first item)
fszontagh 6 månader sedan
förälder
incheckning
a0d106840b
1 ändrade filer med 70 tillägg och 19 borttagningar
  1. 70 19
      nodes/ocr/ocr-upload.js

+ 70 - 19
nodes/ocr/ocr-upload.js

@@ -2,7 +2,7 @@
  * @node ocr-upload
  * @name OCR Upload
  * @category ocr
- * @version 1.0.1
+ * @version 1.2.0
  * @description Upload a file for OCR processing via pdftoimageapi
  * @icon file-scan
  */
@@ -10,6 +10,11 @@
 const configSchema = {
     type: 'object',
     properties: {
+        fileSource: {
+            type: 'string',
+            title: 'File Source',
+            description: 'Path to file data (e.g., {{item.attachments[0]}} for loop iterations, or {{data.attachments[0]}} for direct input). Leave empty to auto-detect from input.'
+        },
         baseUrl: {
             type: 'string',
             title: 'API Base URL',
@@ -90,7 +95,22 @@ const outputs = [
 ];
 
 function isBinaryInput(input) {
-    return input && input.type === 'binary' && typeof input.data === 'string';
+    // Binary input can have either data (base64) or filePath (disk reference)
+    return input && input.type === 'binary' && (typeof input.data === 'string' || typeof input.filePath === 'string');
+}
+
+function resolveBinaryData(file) {
+    // If file has filePath, read from disk
+    if (file.filePath && !file.data) {
+        const readResult = smartbotic.fs.readFile(file.filePath, 'base64');
+        if (readResult.success) {
+            file.data = readResult.data;
+            smartbotic.log.info(`Loaded binary from disk: ${file.filePath}`);
+        } else {
+            throw new Error(`Failed to read file from disk: ${file.filePath} - ${readResult.error}`);
+        }
+    }
+    return file;
 }
 
 function generateBoundary() {
@@ -156,29 +176,60 @@ module.exports = {
         const baseUrl = (config.baseUrl || 'http://localhost:3000').replace(/\/$/, '');
         let file = null;
 
-        if (isBinaryInput(input.file)) {
-            file = input.file;
-        } else if (isBinaryInput(input)) {
-            file = input;
-        } else if (input.storage && input.storage.collection && input.storage.id) {
-            const storageResult = smartbotic.storage.get(input.storage.collection, input.storage.id);
-            if (!storageResult.found) {
-                throw new Error(`File not found in storage: ${input.storage.collection}/${input.storage.id}`);
+        // First priority: use configured fileSource if provided
+        // The expression (e.g., {{item.attachments[0]}}) is evaluated by the workflow engine,
+        // so config.fileSource contains the actual file object
+        if (config.fileSource && typeof config.fileSource === 'object') {
+            if (isBinaryInput(config.fileSource)) {
+                file = config.fileSource;
+                smartbotic.log.info('OCR Upload: Using configured file source');
+            } else if (Array.isArray(config.fileSource) && config.fileSource.length > 0) {
+                // If fileSource resolved to an array (e.g., attachments array), use first item
+                file = config.fileSource[0];
+                smartbotic.log.info(`OCR Upload: Using first item from configured file source array: ${file.filename}`);
             }
-            const doc = storageResult.document;
-            file = {
-                type: 'binary',
-                data: doc.data,
-                mimeType: doc.mimeType,
-                filename: doc.filename,
-                size: doc.size
-            };
         }
 
+        // Fallback: auto-detect from various input formats
         if (!file) {
-            throw new Error('No file provided. Provide either a binary file object or a storage reference.');
+            if (isBinaryInput(input.file)) {
+                file = input.file;
+            } else if (isBinaryInput(input)) {
+                file = input;
+            } else if (input.data && isBinaryInput(input.data)) {
+                // Handle data wrapper from upstream nodes
+                file = input.data;
+            } else if (input.attachments && Array.isArray(input.attachments) && input.attachments.length > 0) {
+                // Handle output from IMAP Extract Attachments - use first attachment
+                file = input.attachments[0];
+                smartbotic.log.info(`Using first attachment from array: ${file.filename}`);
+            } else if (input.storage && input.storage.collection && input.storage.id) {
+                // Load from storage database (metadata with filePath)
+                const storageResult = smartbotic.storage.get(input.storage.collection, input.storage.id);
+                if (!storageResult.found) {
+                    throw new Error(`File not found in storage: ${input.storage.collection}/${input.storage.id}`);
+                }
+                const doc = storageResult.document;
+                file = {
+                    type: 'binary',
+                    filePath: doc.filePath,  // Reference to disk location
+                    mimeType: doc.mimeType,
+                    filename: doc.filename,
+                    size: doc.size
+                };
+            }
         }
 
+        if (!file) {
+            // Log available input keys for debugging
+            const inputKeys = Object.keys(input || {}).join(', ');
+            smartbotic.log.warn(`OCR Upload: No binary file found. Input keys: ${inputKeys}`);
+            throw new Error('No file provided. Configure the "File Source" field with an expression like {{item.attachments[0]}} for loop iterations, or connect to IMAP Extract Attachments.');
+        }
+
+        // Resolve file data from disk if needed
+        file = resolveBinaryData(file);
+
         const headers = {};
 
         if (config.credentialId) {