Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@natcl

natcl/README.md Secret

Last active October 18, 2022 19:18
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save natcl/5805a1141b1212d2c55c1781b9dbd15b to your computer and use it in GitHub Desktop.
Save natcl/5805a1141b1212d2c55c1781b9dbd15b to your computer and use it in GitHub Desktop.
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":[[]]}]
@andreapx
Copy link

Hi, I've tried this subflow, but no metter what file I try to upload, it says: Error: only files are allowed.

@aniston
Copy link

aniston commented Sep 26, 2022

@andreapx the "File Upload" SubFlow properties needs a correctly assigned array (the default array is blank), in my example its allowing for .json and .log files ["json","log"]

image
HTH.

PS: it does not list hidden files or sub-directories, most possibly it's design intented.

@andreapx
Copy link

Thanks!!!

@naybre01
Copy link

naybre01 commented Oct 18, 2022

Hi I seem to be getting a upload permission error on dietpi is there something I might be doing wrong

failed to write to file: Error: EACCES: permission denied, open './Leave the area with tone.wav'

@natcl
Copy link
Author

natcl commented Oct 18, 2022

Make sure you set UPLOAD_DIR to a directory you have write access to, seems like you’re trying to write at the root of the filesystem…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment