File upload and delete in Dashboard

This is a simple subflow that will allow you to upload files in the Dashboard and also select and delete them. The directory to upload to is defined by the UPLOAD_DIR subflow environement variable. You can also specify allowed extensions in the EXTENSIONS environement variable.

[{"id":"4f6b87ae.7d3bb","type":"subflow","name":"List Files","info":"# List files\n\nWill list files in a directory.\n\nPath can be set in `msg.payload` or by setting the `DIRECTORY` environment variable.\n\nExtensions can be filtered by settings the `EXTENSIONS` environment variable to an Array of extensions.\n","category":"","in":[{"x":80,"y":80,"wires":[{"id":"cf0b484b.b70c9"}]}],"out":[{"x":840,"y":40,"wires":[{"id":"13486428.bcfc4c","port":0}]}],"env":[{"name":"DIRECTORY","type":"str","value":""},{"name":"EXTENSIONS","type":"json","value":"[]"}]},{"id":"208379c0.81563e","type":"exec","z":"4f6b87ae.7d3bb","command":"ls","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":510,"y":60,"wires":[["13486428.bcfc4c"],[],[]]},{"id":"13486428.bcfc4c","type":"change","z":"4f6b87ae.7d3bb","name":"split and filter","rules":[{"t":"set","p":"payload","pt":"msg","to":"(\t    $files := [$split(payload, '\\n')[$ != \"\"]];\t    $count($env('EXTENSIONS')) = 0 ? [$files] : [$files[$split($, '.')[-1] in $env('EXTENSIONS')]];\t)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":680,"y":40,"wires":[[]]},{"id":"cf0b484b.b70c9","type":"switch","z":"4f6b87ae.7d3bb","name":"","property":"$env('DIRECTORY')","propertyType":"jsonata","rules":[{"t":"empty"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":210,"y":80,"wires":[["208379c0.81563e"],["56426a5a.fbc44c"]]},{"id":"56426a5a.fbc44c","type":"change","z":"4f6b87ae.7d3bb","name":"DIRECTORY","rules":[{"t":"set","p":"payload","pt":"msg","to":"DIRECTORY","tot":"env"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":120,"wires":[["208379c0.81563e"]]},{"id":"19ad2b6f.f11b85","type":"subflow","name":"FIle Upload","info":"","category":"","in":[],"out":[{"x":1140,"y":280,"wires":[{"id":"144a9c8f.af7e9b","port":0},{"id":"854a9fb8.a668a8","port":0}]}],"env":[{"name":"UPLOAD_DIR","type":"str","value":"."},{"name":"EXTENSIONS","type":"json","value":"[]"}],"outputLabels":["fileWritten"]},{"id":"954c0325.f4f63","type":"http in","z":"19ad2b6f.f11b85","name":"","url":"/fileupload","method":"post","upload":true,"swaggerDoc":"","x":140,"y":440,"wires":[["7433a631.a7f58","faf9ee8.6642a1"]]},{"id":"964d2a30.34e938","type":"http response","z":"19ad2b6f.f11b85","name":"","statusCode":"","headers":{},"x":850,"y":440,"wires":[]},{"id":"1617f361.5dac2d","type":"ui_template","z":"19ad2b6f.f11b85","group":"4178bf61.05d97","name":"Upload","order":1,"width":"6","height":"3","format":"<form id=\"upload_form\" enctype=\"multipart/form-data\" method=\"post\">\n    <input type=\"file\" name=\"file1\" id=\"file1\"><br>\n    <input type=\"button\" value=\"Upload File\" onclick=\"uploadFile()\">\n    <progress id=\"progressBar\" value=\"0\" max=\"100\" style=\"width:300px;\"></progress>\n    <p id=\"status\"></p>\n    <p id=\"loaded_n_total\"></p>\n</form>\n\n<script>\n    function _(el){\n    return document.getElementById(el);\n}\nfunction uploadFile(){\n    var file = _(\"file1\").files[0];\n    // alert(file.name+\" | \"+file.size+\" | \"+file.type);\n    var formdata = new FormData();\n    formdata.append(\"file1\", file);\n    var ajax = new XMLHttpRequest();\n    ajax.upload.addEventListener(\"progress\", progressHandler, false);\n    ajax.addEventListener(\"load\", completeHandler, false);\n    ajax.addEventListener(\"error\", errorHandler, false);\n    ajax.addEventListener(\"abort\", abortHandler, false);\n    ajax.open(\"POST\", \"/fileupload\");\n    ajax.send(formdata);\n}\nfunction progressHandler(event){\n    _(\"loaded_n_total\").innerHTML = \"Uploaded \"+event.loaded+\" bytes of \"+event.total;\n    var percent = (event.loaded / event.total) * 100;\n    _(\"progressBar\").value = Math.round(percent);\n    _(\"status\").innerHTML = Math.round(percent)+\"% uploaded... please wait\";\n}\nfunction completeHandler(event){\n    _(\"status\").innerHTML = event.target.responseText;\n    _(\"progressBar\").value = 0;\n}\nfunction errorHandler(event){\n    _(\"status\").innerHTML = \"Upload Failed\";\n}\nfunction abortHandler(event){\n    _(\"status\").innerHTML = \"Upload Aborted\";\n}\n</script>","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":120,"y":400,"wires":[[]]},{"id":"ea605dad.7b36a8","type":"subflow:4f6b87ae.7d3bb","z":"19ad2b6f.f11b85","name":"","env":[{"name":"DIRECTORY","type":"env","value":"UPLOAD_DIR"},{"name":"EXTENSIONS","type":"env","value":"EXTENSIONS"}],"x":380,"y":140,"wires":[["b42b38bf.d5a548"]]},{"id":"a425ba62.ff1df","type":"ui_dropdown","z":"19ad2b6f.f11b85","name":"","label":"","tooltip":"","place":"Select option","group":"4178bf61.05d97","order":0,"width":0,"height":0,"passthru":true,"options":[{"label":"","value":"","type":"str"}],"payload":"","topic":"","x":750,"y":140,"wires":[["62157c1a.4444bc"]]},{"id":"bdb6a329.8574b","type":"link in","z":"19ad2b6f.f11b85","name":"refreshFileDropdown","links":["15ae2641.f1cc7a","be23c76f.4a3988"],"x":75,"y":140,"wires":[["f0813c91.8c7838"]]},{"id":"51272d56.830874","type":"ui_button","z":"19ad2b6f.f11b85","name":"","group":"4178bf61.05d97","order":0,"width":0,"height":0,"passthru":false,"label":"Delete","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":110,"y":220,"wires":[["a0bbc93d.d6f6b8"]]},{"id":"62157c1a.4444bc","type":"change","z":"19ad2b6f.f11b85","name":"","rules":[{"t":"set","p":"selectedFile","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":960,"y":140,"wires":[[]]},{"id":"7433a631.a7f58","type":"change","z":"19ad2b6f.f11b85","name":"getFile","rules":[{"t":"set","p":"filename","pt":"msg","to":"$env('UPLOAD_DIR')  & '/' & req.files[0].originalname","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"req.files[0].buffer","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":360,"wires":[["63e6ebc1.1cc124"]]},{"id":"10c1284a.0e3f98","type":"file","z":"19ad2b6f.f11b85","name":"","filename":"","appendNewline":false,"createDir":true,"overwriteFile":"true","x":830,"y":340,"wires":[["144a9c8f.af7e9b"]]},{"id":"af0d1f9b.6eb468","type":"inject","z":"19ad2b6f.f11b85","name":"","topic":"","payload":"","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":130,"y":80,"wires":[["f0813c91.8c7838"]]},{"id":"a0bbc93d.d6f6b8","type":"change","z":"19ad2b6f.f11b85","name":"getSelectedFile","rules":[{"t":"set","p":"filename","pt":"msg","to":"$env('UPLOAD_DIR')  & '/' & $flowContext('selectedFile')","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"Delete File ?","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":280,"y":220,"wires":[["3e909d09.b8b5f2"]]},{"id":"854a9fb8.a668a8","type":"file","z":"19ad2b6f.f11b85","name":"","filename":"","appendNewline":true,"createDir":false,"overwriteFile":"delete","x":830,"y":220,"wires":[["be23c76f.4a3988"]]},{"id":"3e909d09.b8b5f2","type":"ui_toast","z":"19ad2b6f.f11b85","position":"dialog","displayTime":"3","highlight":"","outputs":1,"ok":"OK","cancel":"Cancel","topic":"","name":"","x":470,"y":220,"wires":[["a33238b4.01cae"]]},{"id":"a33238b4.01cae","type":"switch","z":"19ad2b6f.f11b85","name":"OK ?","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"OK","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":630,"y":220,"wires":[["854a9fb8.a668a8"]]},{"id":"b54a9427.62f75","type":"catch","z":"19ad2b6f.f11b85","name":"","scope":null,"x":120,"y":500,"wires":[["1a19fda8.e72fd2"]]},{"id":"563135cc.7b97e4","type":"ui_toast","z":"19ad2b6f.f11b85","position":"top right","displayTime":"5","highlight":"","sendall":true,"outputs":0,"ok":"OK","cancel":"","raw":false,"topic":"","name":"","x":530,"y":500,"wires":[]},{"id":"1a19fda8.e72fd2","type":"change","z":"19ad2b6f.f11b85","name":"getError","rules":[{"t":"set","p":"payload","pt":"msg","to":"error.message","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":300,"y":500,"wires":[["563135cc.7b97e4"]]},{"id":"be23c76f.4a3988","type":"link out","z":"19ad2b6f.f11b85","name":"refreshAfterDelete","links":["bdb6a329.8574b"],"x":1135,"y":220,"wires":[]},{"id":"15ae2641.f1cc7a","type":"link out","z":"19ad2b6f.f11b85","name":"refreshAfterUpload","links":["bdb6a329.8574b"],"x":1135,"y":340,"wires":[]},{"id":"faf9ee8.6642a1","type":"change","z":"19ad2b6f.f11b85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"'File ' & req.files[0].originalname & ' uploaded.'","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":460,"y":440,"wires":[["964d2a30.34e938"]]},{"id":"f0813c91.8c7838","type":"delay","z":"19ad2b6f.f11b85","name":"","pauseType":"delay","timeout":"100","timeoutUnits":"milliseconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":190,"y":140,"wires":[["ea605dad.7b36a8"]]},{"id":"a5f544d.69b9bb8","type":"watch","z":"19ad2b6f.f11b85","name":"","files":"$(UPLOAD_DIR)","recursive":"","x":140,"y":40,"wires":[["f0813c91.8c7838"]]},{"id":"b42b38bf.d5a548","type":"change","z":"19ad2b6f.f11b85","name":"options","rules":[{"t":"set","p":"options","pt":"msg","to":"payload","tot":"msg"},{"t":"delete","p":"payload","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":140,"wires":[["a425ba62.ff1df"]]},{"id":"63e6ebc1.1cc124","type":"switch","z":"19ad2b6f.f11b85","name":"extensionAllowed ?","property":"$env('EXTENSIONS')","propertyType":"jsonata","rules":[{"t":"cont","v":"$split(filename, '.')[-1]","vt":"jsonata"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":610,"y":360,"wires":[["10c1284a.0e3f98"],["e34d7e40.c64b5"]]},{"id":"e34d7e40.c64b5","type":"function","z":"19ad2b6f.f11b85","name":"Error","func":"node.error(`Error: only ${env.get('EXTENSIONS')} files are allowed.`, msg)\n","outputs":0,"noerr":0,"x":830,"y":380,"wires":[]},{"id":"144a9c8f.af7e9b","type":"change","z":"19ad2b6f.f11b85","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":1000,"y":340,"wires":[["15ae2641.f1cc7a"]]},{"id":"4178bf61.05d97","type":"ui_group","z":"","name":"File upload","tab":"f1b5a1b6.543fd8","order":4,"disp":true,"width":"6","collapse":false},{"id":"f1b5a1b6.543fd8","type":"ui_tab","z":"","name":"File Upload","icon":"dashboard","order":4},{"id":"3696af61.5b451","type":"subflow:19ad2b6f.f11b85","z":"c178a9c2.3fd318","name":"","env":[],"x":270,"y":700,"wires":[[]]}]

Flow Info

Created 4 years, 7 months ago
Updated 3 years, 9 months ago
Rating: 5 2

Owner

Actions

Rate:

Node Types

Core
  • catch (x1)
  • change (x9)
  • delay (x1)
  • exec (x1)
  • file (x2)
  • function (x1)
  • http in (x1)
  • http response (x1)
  • inject (x1)
  • link in (x1)
  • link out (x2)
  • switch (x3)
  • watch (x1)
Other
  • subflow (x2)
  • subflow:19ad2b6f.f11b85 (x1)
  • subflow:4f6b87ae.7d3bb (x1)
  • ui_button (x1)
  • ui_dropdown (x1)
  • ui_group (x1)
  • ui_tab (x1)
  • ui_template (x1)
  • ui_toast (x2)

Tags

  • file
  • upload
  • dashboard
  • subflow
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option