Hello all,
I am not sure if this is the right category to share this, but i have been walking in circles when figuring out how to best add files from OpenFlow to a Workitem in NodeRED.
I did however come up with a method, I am very curious to see other approaches, so please feel free to share
I created this subflow in NodeRED to simplify things a bit.
this can be imported directly in NodeRED
Documentation
[
{
"id": "5eb293961cf0e7ac",
"type": "subflow",
"name": "Get files from OpenFlow",
"info": "A subflow to get files from OpenFlow\r\n\r\n### Node-inputs\r\n\r\n_msg:_\r\n - `msg.uniquenames`\r\n\r\nAn array of strings containing the uniquenames you want to retireve\r\nfrom the files colleciton.\r\n - `msg.filetemplates`\r\n \r\nShould contain an array of filetemplate objects following this structure:\r\n\r\nmsg.filetemplates=\r\n`[`\r\n\r\n {\"fileref\": \"exampleOne\",\r\n \"uniquename\": \"example1-34h5435-3e454-4fa2-4534e-erwdf3t3.xlsx\"},\r\n\r\n {\"fileref\": \"exampleTwo\",\r\n \"uniquename\": \"example2-43fdew-8fgh-5fj9-fs2ag-01vs3.xlsx\"}\r\n`]`\r\n\r\n\r\n_env:_\r\n- `uniquename`\r\n\r\nPrimarily used to test and retrieve single static file\r\nfrom uniquename as string.\r\n\r\n**OBS: if provided flow will only use this**\r\n\r\n### Node-outputs\r\nExpected output given input\r\n\r\n - _uniquename_(env)\r\n\r\nSingle file object in an array\r\n\r\n` msg.files` =>[_fileObject_]\r\n\r\n - _msg.uniquenames_\r\n\r\nMultiple file object in an array\r\n\r\n `msg.files` => [_fileObject1_,_fileObject2_]\r\n\r\n - _msg.filetemplates_\r\n\r\nReturns an object of objects based on the references given in the filetemplates for each file.\r\n\r\nExample based on input:\r\n\r\n `msg.getfiles` =>\r\n `{`\r\n \r\n \"exampleOne\": {fileObject},\r\n \r\n \"exampleTwo\": {fileObject}\r\n \r\n `}`\r\n\r\nCan access each fileObjects using fileref from filetemplates:\r\n\r\n`msg.getfile`.exampleOne\r\n\r\n`msg.getfile`.exampleTwo\r\n\r\n\r\n\r\n\r\n",
"category": "OpenFlow",
"in": [
{
"x": 90,
"y": 320,
"wires": [
{
"id": "d96172cb3102a8a3"
}
]
}
],
"out": [
{
"x": 1480,
"y": 500,
"wires": [
{
"id": "7d2033ad96071bf3",
"port": 0
}
]
}
],
"env": [
{
"name": "uniquename",
"type": "str",
"value": "",
"ui": {
"icon": "font-awesome/fa-file-o",
"type": "input",
"opts": {
"types": [
"str"
]
}
}
}
],
"meta": {},
"color": "#3FADB5",
"icon": "font-awesome/fa-angle-double-down",
"status": {
"x": 1320,
"y": 580,
"wires": [
{
"id": "15cab6f14fcc7d79",
"port": 0
},
{
"id": "bd21494e3beb8f17",
"port": 0
}
]
}
},
{
"id": "34b7c7445ddd9306",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Prepare query - files",
"func": "let query = {\n \"metadata.uniquename\": {\n $in: msg.uniquenames\n }\n};\n\nmsg.query = query;\n\nmsg.files = []\n\nreturn msg; // Return the modified msg object\n",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 630,
"y": 380,
"wires": [
[
"bd6c9a8e08be4bc4"
]
]
},
{
"id": "bd6c9a8e08be4bc4",
"type": "api get",
"z": "5eb293961cf0e7ac",
"name": "api get - files",
"query": "query",
"querytype": "msg",
"projection": "",
"projectiontype": "str",
"top": 500,
"toptype": "num",
"skip": 0,
"skiptype": "num",
"collection": "files",
"collectiontype": "str",
"resultfield": "queryRes",
"resultfieldtype": "msg",
"orderby": "",
"orderbytype": "str",
"x": 660,
"y": 440,
"wires": [
[
"f17bc31e6315f665"
]
]
},
{
"id": "fe0855616b828e34",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Fetch env variable",
"func": "// Prepare object with file refs\nmsg.getfile = {}\n\n// Prepare list of filenames\nlet array_of_filenames = []\n\n// Fetch environment variables\nconst env_file_names = env.get(\"uniquename\")\n\n//If environment variable is provided use this, otherwise use msg.filetemplate if provided\nif (env_file_names !== \"\"){\n array_of_filenames = [env_file_names]\n\n}\nelse{\n if(typeof(msg.uniquenames) !== \"undefined\"){\n array_of_filenames = msg.uniquenames\n }\n else{\n if (typeof (msg.filetemplates) !== \"undefined\" && Array.isArray(msg.filetemplates)) {\n // Use forEach to iterate over the array\n msg.filetemplates.forEach(function(element) {\n if (element.uniquename) {\n array_of_filenames.push(element.uniquename);\n }\n });\n }\n else{\n node.error(\"Missing list of unique filenames\", msg);\n msg.payload = {fill: \"red\", shape: \"dot\", text: \"FAILED\" }\n return [msg, null]\n }\n }\n}\n\nmsg.uniquenames = array_of_filenames\n\nreturn [null, msg]",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 560,
"y": 320,
"wires": [
[
"b40f8b526665823b"
],
[
"34b7c7445ddd9306"
]
],
"outputLabels": [
"ERROR",
"OK"
]
},
{
"id": "bd21494e3beb8f17",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Analyse/prepare result",
"func": "// Analysis feedback\nlet files_retrieved = msg.files.length\nlet files_requested = msg.uniquenames.length\nlet status_msg = \"Retrieved \" + files_retrieved + \"/\" + files_requested + \" files\"\n\nif(files_retrieved === files_requested){\n msg.payload = {fill:\"green\",shape:\"ring\",text: status_msg}\n}\nelse if (files_retrieved === 0){\n msg.payload = { fill: \"red\", shape: \"ring\", text: status_msg}\n}\nelse{\n msg.payload = { fill: \"yellow\", shape: \"ring\", text: status_msg}\n}\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1150,
"y": 540,
"wires": [
[
"7d2033ad96071bf3"
]
]
},
{
"id": "7df552f92f62234b",
"type": "api download file",
"z": "5eb293961cf0e7ac",
"fileid": "file._id",
"fileidtype": "msg",
"filename": "file.filename",
"filenametype": "msg",
"result": "fileContent",
"resulttype": "msg",
"asbuffer": true,
"name": "",
"x": 900,
"y": 560,
"wires": [
[
"1959f835facdb4d7"
]
]
},
{
"id": "1959f835facdb4d7",
"type": "link out",
"z": "5eb293961cf0e7ac",
"name": "link out 38",
"mode": "link",
"links": [
"98341b97fe65d372"
],
"x": 1045,
"y": 600,
"wires": []
},
{
"id": "98341b97fe65d372",
"type": "link in",
"z": "5eb293961cf0e7ac",
"name": "link in 10",
"links": [
"1959f835facdb4d7"
],
"x": 575,
"y": 500,
"wires": [
[
"f41d718560049fb7"
]
]
},
{
"id": "f41d718560049fb7",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Populate files",
"func": "// File content\nconst file_content = msg.fileContent\n\n// Remove from first not allowed character\nconst filename = msg.file.filename\n\nlet fileKey = filename\nmsg.files.push({\n \"file\": file_content,\n \"filename\": filename\n})\n\n// Find the object with the matching uniquename\nif(typeof(msg.filetemplates) !== \"undefined\"){\n let matchingObject = msg.filetemplates.find(obj => obj.uniquename === msg.file.metadata.uniquename)\n let refname = matchingObject.fileref\n\n let value = {\n \"name\": filename,\n \"file\" : file_content\n }\n\n msg.getfile[refname] = value\n}\n\nreturn msg",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 690,
"y": 500,
"wires": [
[
"f17bc31e6315f665"
]
]
},
{
"id": "f17bc31e6315f665",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Pop result",
"func": "// pop file\nmsg.file = msg.queryRes.pop()\n\n// Exit if no file popped\nif(typeof(msg.file) === \"undefined\"){\n return [msg, null]\n}\n\nreturn [null, msg];",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 870,
"y": 500,
"wires": [
[
"bd21494e3beb8f17"
],
[
"7df552f92f62234b"
]
],
"outputLabels": [
"Done",
"Got file"
]
},
{
"id": "d96172cb3102a8a3",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "Status",
"func": "msg.payload = { fill: \"blue\", shape: \"ring\", text: \"Running\" }\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 200,
"y": 320,
"wires": [
[
"d5dcb816bc9dedeb",
"00774aff73059876"
]
]
},
{
"id": "d5dcb816bc9dedeb",
"type": "delay",
"z": "5eb293961cf0e7ac",
"name": "",
"pauseType": "delay",
"timeout": "1",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 360,
"y": 320,
"wires": [
[
"fe0855616b828e34"
]
]
},
{
"id": "00774aff73059876",
"type": "link out",
"z": "5eb293961cf0e7ac",
"name": "link out 39",
"mode": "link",
"links": [
"15cab6f14fcc7d79"
],
"x": 325,
"y": 260,
"wires": []
},
{
"id": "15cab6f14fcc7d79",
"type": "link in",
"z": "5eb293961cf0e7ac",
"name": "link in 11",
"links": [
"00774aff73059876"
],
"x": 1245,
"y": 620,
"wires": [
[]
]
},
{
"id": "b40f8b526665823b",
"type": "link out",
"z": "5eb293961cf0e7ac",
"name": "link out 40",
"mode": "link",
"links": [
"ef64a2616fc46aea"
],
"x": 705,
"y": 280,
"wires": []
},
{
"id": "ef64a2616fc46aea",
"type": "link in",
"z": "5eb293961cf0e7ac",
"name": "link in 12",
"links": [
"b40f8b526665823b"
],
"x": 265,
"y": 220,
"wires": [
[
"00774aff73059876"
]
]
},
{
"id": "7d2033ad96071bf3",
"type": "function",
"z": "5eb293961cf0e7ac",
"name": "cleanup",
"func": "// Cleanup\ndelete msg.payload.fill\ndelete msg.payload.shape\ndelete msg.payload.text\ndelete msg.payload.status\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 1360,
"y": 500,
"wires": [
[]
]
},
{
"id": "39e5a6a425601388",
"type": "subflow:5eb293961cf0e7ac",
"z": "5501d9bc7c2c1c8f",
"name": "",
"x": 610,
"y": 4020,
"wires": [
[
"16ff98fcc7d211d5"
]
]
}
]