# Ftp to browse sub directories

**URL:** <https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189>\
**Category:** General\
**Created:** [13 June 2019 15:34 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189 "2019-06-13T15:34:18Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![oli.nodered](https://avatars.discourse-cdn.com/v4/letter/o/e9bcb4/32.png) [@oli.nodered](https://discourse.nodered.org/u/oli.nodered)\
**Post date:** [13 June 2019 15:34 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/1 "2019-06-13T15:34:18Z")

</div>

Bonjour  
i use the node red ftp node to List the directory on a server.  
it is ok for the root, i have got all informations.  
i have two directories and i want to browse now the sub directories and i didn't found the syntax.  
Can you help me  
Merci  
Olivier

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [13 June 2019 16:55 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/2 "2019-06-13T16:55:26Z")

</div>

Seeing that there a number of ftp nodes it would be helpful to know which one you are using

---

<div class="post-metadata">

**Author:** ![oli.nodered](https://avatars.discourse-cdn.com/v4/letter/o/e9bcb4/32.png) [@oli.nodered](https://discourse.nodered.org/u/oli.nodered)\
**Post date:** [13 June 2019 17:22 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/3 "2019-06-13T17:22:52Z")

</div>

i use this one [https://flows.nodered.org/node/node-red-contrib-ftp](https://flows.nodered.org/node/node-red-contrib-ftp)  
but i can use another node if it is more simple.  
Merci

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [13 June 2019 19:07 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/4 "2019-06-13T19:07:31Z")

</div>

I haven't used it, but you might look at node-red-contrib-ftp-download

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [15 June 2019 08:56 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/5 "2019-06-15T08:56:54Z")

</div>

> [@oli.nodered](#):
>
> i have two directories and i want to browse now the sub directories and i didn't found the syntax.

What have you tried? Perhaps post the relevant part of your flow & someone will take a look?

Looking at that node you linked to, it supports LIST and permits you to send msg.filename. it may be possible to set the path you want to LIST in msg.filename? Give it a try.

I realize the bumf states...  
`The LIST option returns an array of the file/folders in the user's default ftp folder, containing type`

If it ONLY lists the root directory then it's a bit of a shortcoming. Perhaps raise an issue on its git repo?

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [1 May 2020 15:06 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/6 "2020-05-01T15:06:23Z")

</div>

Hi all, i need help too :  
i test : [https://flows.nodered.org/node/node-red-contrib-ftp](https://flows.nodered.org/node/node-red-contrib-ftp) and the list show me 5 folders , that's true.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/2/020f59467d802db0abc94720a567c64162aeb0af.png)

But there is also sub-folder like this : `FTPserver\192.168.1.7_0012411adb55\2020-05-01\01\pic`

i test : [https://flows.nodered.org/node/node-red-contrib-ftp-download](https://flows.nodered.org/node/node-red-contrib-ftp-download) too but with same issue.

My cameras record the movements (pictures) on an FTP server and I would like to view them in the dashboard.

I know how to do it locally with [https://flows.nodered.org/node/node-red-contrib-fs-ops](https://flows.nodered.org/node/node-red-contrib-fs-ops), but in FTP I get stuck 😢

has someone successfully accessed a FTP subfolder?

---

<div class="post-metadata">

**Author:** ![afelix](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/afelix/32/9743_2.png) [@afelix](https://discourse.nodered.org/u/afelix)\
**Post date:** [2 May 2020 14:00 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/7 "2020-05-02T14:00:31Z")

</div>

See the previous answer:

> [@Steve-Mcl](#):
>
> If it ONLY lists the root directory then it's a bit of a shortcoming. Perhaps raise an issue on its git repo?

In fact, two issues for it have been raised:

> <https://github.com/joeartsea/node-red-contrib-ftp/issues/10>
>
> How can I do a \`list \`on a sub-folder please, ideally with a filter. e.g.
> 
> di…r anon/www/test/\*.gif

> <https://github.com/joeartsea/node-red-contrib-ftp/issues/19>
>
> Hello, I was in need of listing subdirectories within FTP and I ended up editing… your \*\*ftp.js\*\* and \*\*ftp.html\*\* code, and implemented this option. If you are interested in using it to update your library, I think it would be interesting :)
> 
> Follows the code:
> 
> ftp.js:
> 
> \`\`\`
> module.exports = function (RED) {
> 'use strict';
> var ftp = require('ftp');
> var fs = require('fs');
> 
> function FtpNode(n) {
> RED.nodes.createNode(this, n);
> var node = this;
> var credentials = RED.nodes.getCredentials(n.id);
> this.options = {
> 'host': n.host || 'localhost',
> 'port': n.port || 21,
> 'secure': n.secure || false,
> 'secureOptions': n.secureOptions,
> 'user': n.user || 'anonymous',
> 'password': credentials.password || 'anonymous@',
> 'connTimeout': n.connTimeout || 10000,
> 'pasvTimeout': n.pasvTimeout || 10000,
> 'keepalive': n.keepalive || 10000
> };
> }
> 
> RED.nodes.registerType('ftp', FtpNode, {
> credentials: {
> password: { type: 'password' }
> }
> });
> 
> function FtpInNode(n) {
> RED.nodes.createNode(this, n);
> this.ftp = n.ftp;
> this.operation = n.operation;
> this.filename = n.filename;
> this.localFilename = n.localFilename;
> this.ftpConfig = RED.nodes.getNode(this.ftp);
> 	
> if (this.ftpConfig) {
> var node = this;
> node.on('input', function (msg) {
> var conn = new ftp();
> var filename = node.filename || msg.filename || '';
> var localFilename = node.localFilename || msg.localFilename || '';
> this.sendMsg = function (err, result) {
> if (err) {
> node.error(err, msg);
> node.status({ fill: 'red', shape: 'ring', text: 'failed' });
> node.send(err);
> return;
> }
> node.status({});
> if (node.operation == 'get') {
> result.once('close', function() { conn.end(); });
> result.pipe(fs.createWriteStream(localFilename));
> msg.payload = 'Get operation successful. ' + localFilename;
> } else if (node.operation == 'put') {
> conn.end();
> msg.payload = 'Put operation successful.';
> } else {
> conn.end();
> msg.message = 'Operation successful.';
> msg.payload = result;
> }
> msg.filename = filename;
> msg.localFilename = localFilename;
> node.send(msg);
> };
> conn.on('ready', function () {
> switch (node.operation) {
> case 'list':
> conn.list(filename, node.sendMsg);
> break;
> case 'get':
> conn.get(filename, node.sendMsg);
> break;
> case 'put':
> conn.put(localFilename, filename, node.sendMsg);
> break;
> case 'delete':
> conn.delete(filename, node.sendMsg);
> break;
> }
> });
> conn.on('error', function(err) { 
> node.error(err, msg);
> node.status({ fill: 'red', shape: 'ring', text: err.message });
> node.send(err);
> return;
> });
> conn.connect(node.ftpConfig.options);
> });
> } else {
> this.error('missing ftp configuration');
> }
> }
> RED.nodes.registerType('ftp in', FtpInNode);
> }
> \`\`\`
> 
> ftp.html:
> 
> \`\`\`
> \<script type="text/x-red" data-template-name="ftp"\>
> \<div class="form-row"\>
> \<label for="node-config-input-host"\>\<i class="fa fa-bookmark"\>\</i\> Host\</label\>
> \<input type="text" id="node-config-input-host" placeholder="localhost" style="width: 40%;" /\>
> \<label for="node-config-input-port" style="margin-left: 10px; width: 35px; "\> Port\</label\>
> \<input type="text" id="node-config-input-port" placeholder="21" style="width:45px"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-config-input-user"\>\<i class="fa fa-user"\>\</i\> User\</label\>
> \<input type="text" id="node-config-input-user" placeholder="anonymous" /\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-config-input-password"\>\<i class="fa fa-lock"\>\</i\> Password\</label\>
> \<input type="password" id="node-config-input-password"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-config-input-connTimeout"\>\<i class="fa fa-clock-o"\>\</i\> Connection Timeout\</label\>
> \<input type="text" id="node-config-input-connTimeout" placeholder="10000"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-config-input-pasvTimeout"\>\<i class="fa fa-clock-o"\>\</i\> PASV Timeout\</label\>
> \<input type="text" id="node-config-input-pasvTimeout" placeholder="10000"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-config-input-keepalive"\>\<i class="fa fa-clock-o"\>\</i\> Keepalive\</label\>
> \<input type="text" id="node-config-input-keepalive" placeholder="10000"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-input-secure"\>\<i class="fa fa-key"\>\</i\> Data connection encryption\</label\>
> \<input type="checkbox" id="node-input-secure" placeholder="once" style="width: 10%; vertical-align: top;"\>
> \<label for="node-config-input-secureOptions" style="width: 20%; vertical-align: top;"\> Secure Options\</label\>
> \<input type="text" id="node-config-input-secureOptions" style="width: 35%; vertical-align: top;"\>
> \</div\>
> \</script\>
> 
> \<script type="text/x-red" data-help-name="ftp in"\>
> \<p\>Allows LIST, GET, PUT and DELETE of files on a remote FTP server.\</p\>
> \<p\>\<code\>msg.filename\</code\> is the path/name of the file on the remote FTP server\</p\>
> \<p\>\<code\>msg.localFilename\</code\> is the path/name of the file on the local machine\</p\>
> \<p\>NOTE: the local machine is where NR is running - this might not be the machine where your browser connects to Node Red.\</p\>
> \<p\>\</p\> 
> \<p\>GET uses \<code\>msg.filename\</code\> and \<code\>msg.localFilename\</code\>\</p\>
> \<p\>PUT uses \<code\>msg.filename\</code\> and \<code\>msg.localFilename\</code\>\</p\>
> \<p\>DELETE uses only \<code\>msg.filename\</code\>\</p\>
> \<p\>LIST uses only \<code\>msg.filename\</code\> and returns an array of the file/folders, containing type, name, sticky, rights(an object), acl, owner, group, size and date.\</p\>
> \<p\>\</p\>
> \<p\>You can pass \<code\>msg.filename\</code\> and \<code\>msg.localFilename\</code\> to this node, however values entered in the node will take precedence.\</p\>
> \<p\>\</p\>
> \<p\>If an error occurs, the error message will come out as \<code\>msg\</code\>.\</p\>
> \</script\>
> 
> \<script type="text/javascript"\>
> RED.nodes.registerType('ftp', {
> category: 'config',
> color:"BurlyWood",
> defaults: {
> host: { value: '' },
> port: { value: '' },
> secure: { value: false },
> secureOptions: { value: '' },
> user: { value: '' },
> connTimeout: { value: '' },
> pasvTimeout: { value: '' },
> keepalive: { value: '' }
> },
> credentials: {
> password: { type: 'password', required: true },
> },
> label: function() {
> return this.host
> }
> });
> \</script\>
> 
> \<script type="text/x-red" data-template-name="ftp in"\>
> \<div class="form-row"\>
> \<label for="node-input-ftp"\>\<i class="fa fa-user"\>\</i\> Add new FTP Server\</label\>
> \<input type="text" id="node-input-ftp"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-input-operation"\>\<i class="fa fa-wrench"\>\</i\> Operation\</label\>
> \<select type="text" id="node-input-operation"\>
> \<option value="list"\>list\</option\>
> \<option value="get"\>get\</option\>
> \<option value="put"\>put\</option\>
> \<option value="delete"\>delete\</option\>
> \</select\>
> \</div\>
> \<div class="form-row input-filename-row hidden"\>
> \<label for="node-input-filename"\>\<i class="fa fa-file"\>\</i\> Filename\</label\>
> \<input type="text" id="node-input-filename" placeholder="Filename"\>
> \</div\>
> \<div class="form-row input-localFilename-row hidden"\>
> \<label for="node-input-localFilename"\>\<i class="fa fa-file"\>\</i\> Local Filename\</label\>
> \<input type="text" id="node-input-localFilename" placeholder="Local Filename"\>
> \</div\>
> \<div class="form-row"\>
> \<label for="node-input-name"\>\<i class="fa fa-tag"\>\</i\> Name\</label\>
> \<input type="text" id="node-input-name" placeholder="Name"\>
> \</div\>
> \</script\>
> 
> \<script type="text/javascript"\>
> RED.nodes.registerType('ftp in', {
> category: 'storage-input',
> color:"BurlyWood",
> defaults: {
> ftp: { type: 'ftp', required: true },
> operation: { value: 'list', required: true },
> filename: { value: '' },
> localFilename: { value: '' },
> name: { value: '' }
> },
> inputs: 1,
> outputs: 1,
> icon: "file.png",
> label: function () {
> var ftpNode = RED.nodes.node(this.ftp);
> return this.name || 'ftp';
> },
> labelStyle: function () {
> return this.name ? 'node\_label\_italic' : '';
> },
> oneditprepare: function () {
> var filename = $(".input-filename-row");
> var localFilename = $(".input-localFilename-row");
> $("#node-input-operation").change(function () {
> var id = $("#node-input-operation option:selected").val();
> console.log(id);
> if (id == 'list') {
> filename.show();
> localFilename.hide();
> } else if (id == 'put' || id == 'get') {
> filename.show();
> localFilename.show();
> } else {
> filename.show();
> localFilename.hide();
> }
> });
> }
> });
> \</script\>
> \`\`\`
> Thanks!

The second of those issues could have been a PR instead as it gives a solution for the author of the node to get it working. You could use that issue though to fix it locally instead.

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [2 May 2020 14:12 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/8 "2020-05-02T14:12:03Z")

</div>

nice i'll test this and come back here !

---

<div class="post-metadata">

**Author:** ![SuperNinja](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/superninja/32/5761_2.png) [@SuperNinja](https://discourse.nodered.org/u/SuperNinja)\
**Post date:** [4 May 2020 09:30 UTC](https://discourse.nodered.org/t/ftp-to-browse-sub-directories/12189/9 "2020-05-04T09:30:27Z")

</div>

Yes it's works !  
See here for newbie (like me) 😉

> [@How to access the folder and sub-folder of an FTP server](https://discourse.nodered.org/t/how-to-access-the-folder-and-sub-folder-of-an-ftp-server/26049):
>
> I wanted to access the sub-folders of an FTP server (created automatically by my surveillance cameras), but the node [https://flows.nodered.org/node/node-red-contrib-ftp](https://flows.nodered.org/node/node-red-contrib-ftp) only displayed the folders root. @afelix found a proposal to modify the original node on the Github: [https://github.com/joeartsea/node-red-contrib-ftp/issues/19](https://github.com/joeartsea/node-red-contrib-ftp/issues/19) You must therefore open the two files found in (RPI example): /home/pi/.node-red/node\_modules/node-red-contrib-ftp Copy / paste in ftp.html : \<script type="text/x-re…
