quorumdms / ftp-srv Goto Github PK
View Code? Open in Web Editor NEW๐ฎ Modern FTP Server
License: MIT License
๐ฎ Modern FTP Server
License: MIT License
Logic here is inverted, causing root
flag to be ignored if it's set.
https://github.com/trs/ftp-srv/tree/update-docs
Edit:
This could also include an update collaborator list, maybe in its own file?
I have used "https://github.com/trs/ftp-srv/blob/master/test/start.js" code to create an FTP Server on localhost. It shows the directory listing correctly in FileZilla. But when I try to transfer a file it fails at STOR directive by throwing Timeout error.
Am I missing anything here?
{"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":10,"msg":"[ 'STOR test.txt' ]","time":"2017-06-13T16:48:18.667Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"directive":"STOR","level":10,"command":{"directive":"STOR","arg":"test.txt","raw":"STOR test.txt"},"msg":"Handle command","time":"2017-06-13T16:48:18.668Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"port":1024,"msg":"Passive connection fulfilled.","time":"2017-06-13T16:48:18.671Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"msg":"Passive connection closed","time":"2017-06-13T16:48:18.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":20,"msg":"Passive server closed","time":"2017-06-13T16:48:18.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"directive":"STOR","level":50,"err":{"message":"timed out after 5000ms","name":"TimeoutError","stack":"TimeoutError: timed out after 5000ms\n at onTimeout (/Users/siddharth.mishra/GitlabRepos/analytics-api-ftp-server/node_modules/when/lib/decorators/timed.js:69:7)\n at Timeout._onTimeout (/Users/siddharth.mishra/GitlabRepos/analytics-api-ftp-server/node_modules/when/lib/decorators/timed.js:13:4)\n at ontimeout (timers.js:380:14)\n at tryOnTimeout (timers.js:244:5)\n at Timer.listOnTimeout (timers.js:214:5)"},"msg":"timed out after 5000ms","time":"2017-06-13T16:48:23.677Z","v":0} {"name":"test","hostname":"SiddharthsMBP2","pid":2623,"id":"64bd4903-a7b2-4ee6-bab7-b8405605ba37","ip":null,"level":10,"port":8880,"packet":"425 No connection established","msg":"Reply","time":"2017-06-13T16:48:23.677Z","v":0}
(Caused by 2a50134.)
When compiling TS which has a dependency to ftp-srv there are some build errors because of mismatching types. The new typed class extension to EventEmitter
causes a problem as the types defined for FtpServer
are incompatible to the base types.
node_modules/ftp-srv/ftp-srv.d.ts(81,5): error TS2416: Property 'emit' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '(action: any, ...data: any[]) => void' is not assignable to type '(event: string | symbol, ...args: any[]) => boolean'.
Type 'void' is not assignable to type 'boolean'.
node_modules/ftp-srv/ftp-srv.d.ts(97,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
Type 'EventEmitter' is not assignable to type 'this'.
node_modules/ftp-srv/ftp-srv.d.ts(113,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
node_modules/ftp-srv/ftp-srv.d.ts(81,5): error TS2416: Property 'emit' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '(action: any, ...data: any[]) => void' is not assignable to type '(event: string | symbol, ...args: any[]) => boolean'.
Type 'void' is not assignable to type 'boolean'.
node_modules/ftp-srv/ftp-srv.d.ts(97,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
Type 'EventEmitter' is not assignable to type 'this'.
node_modules/ftp-srv/ftp-srv.d.ts(113,2): error TS2416: Property 'on' in type 'FtpServer' is not assignable to the same property in base type 'EventEmitter'.
Type '{ (event: "login", listener: (data: { connection: FtpConnection; username: string; password: stri...' is not assignable to type '(event: string | symbol, listener: (...args: any[]) => void) => this'.
I'm trying to upload multiple images at once but only the first one is going through, all parallel requests throw a 530 Command requires authentication
.
It works if I comment out this condition: https://github.com/trs/ftp-srv/blob/master/src/commands/index.js#L56
When uploading a single file I get:
// (command.directive, commandFlags.no_auth, this.connection.authenticated)
USER true undefined
PASS true undefined
TYPE undefined true
PASV undefined true
STOR undefined true
When uploading two files I get:
// (command.directive, commandFlags.no_auth, this.connection.authenticated)
USER true undefined
PASV undefined undefined
PASS true undefined
STOR undefined true
TYPE undefined true
PASV undefined true
STOR undefined true
I guess PASV undefined undefined
is throwing the 530
. Should the PASV
command have a no_auth: true
?
I may be missing the point entirely or not reading the docs correctly, but I don't see a way to do this?
Cheers,
Ed
Hi,
I'm getting this error whenever I upload a file:
(node:49079) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 connection listeners added. Use emitter.setMaxListeners() to increase limit
The upload completes just fine, but I obiously need to address this issue.
I have this in an app that is also running Hapi, but I disabled that and I still get the same error.
By way of a second question. is there an event that fire when a file has been uploaded?
I'm not a node expert and am struggling with how to override the filesystem. I have ftp-srv working fine using the default setup, even running in a docker container.
My application requires receiving a CSV file, converting it to JSON (potentially into a pg database) and send some data to a different REST API. My plan was to override ftp-srv file system based on a login and process the csv file stream into a json file so that I can reply to the ftp client immediately if there are any format errors. If conversion is successful I would then trigger a different process to push data to the REST API while retaining the original file and the JSON version. I may even move this to be done 100% in-memory. Unfortunately, having the third party write directly to our REST API is not an option because they only support FTP transfers. There are other ways I could do this, but there are other benefits for me in this approach that are outside of the scope of this problem.
The documentation on this is light so the best I've been able to determine is to pass a custom FileSystem object with the response from the login event (login event from your test start.js
)
server.on('login', ({connection, username, password}, resolve, reject) => {
if ((username === 'test' || username === 'testdb') && password === 'test' || username === 'anonymous') {
if (username === 'testdb') {
var root = '/code/data';
var cwd = '/';
return resolve({root: root, cwd: cwd, fs: new DbFileSystem(connection, {root: root, cwd: cwd}) });
} else {
return resolve({ root: '/code/data', cwd: '/' });
}
} else {
reject('Bad username or password');
}
});
First of all, is this the right approach?
I then assumed the next step is to extend the FileSystem class:
const { FileSystem } = require('ftp-srv/fs');
const csv = require('csvtojson')
class DbFileSystem extends FileSystem {
constructor(connection, { root, cwd } = {}) {
super(connection, root, cwd);
}
write(fileName, {append = false} = {}) {
const {fsPath} = this._resolvePath(fileName);
const stream = syncFs.createWriteStream(fsPath, {flags: !append ? 'w+' : 'a+'});
stream.on('error', () => fs.unlink(fsPath));
// conceptually, this is what I want to do while the stream is being received
// (I know this function is the wrong place for this code)
csv()
.fromStream(csvReadStream)
.on('csv',(csvRow)=>{
// csvRow is an array
})
.on('done',(error)=>{
})
return stream;
}
}
module.exports = DbFileSystem;
Perhaps this is wrong, but now I don't know where to go next because write only creates a new stream.Writable
and stream is handled asynchrounously in the src/commands/registration/stor.js: handler
. Do I also need to override the STOR
directive? ๐
Thanks
Using RC 3
Im adding TLS using a PFX and passphrase using the following
const pfx = fs.readFileSync(config.TLS_PFX_PATH);
ftpOptions.tls = {
pfx: pfx,
passphrase: config.TLS_PFX_PASSPHRASE,
};
Then Im getting the following errors when I connect and LIST
Note, Im using FileZilla as an FTP client
12:22:24 Status: Disconnected from server
12:22:24 Status: Resolving address of localhost
12:22:24 Status: Connecting to 127.0.0.1:2021...
12:22:24 Status: Connection established, waiting for welcome message...
12:22:24 Response: 220 Ready
12:22:24 Command: AUTH TLS
12:22:24 Response: 234 Honored
12:22:24 Status: Initializing TLS...
12:22:24 Status: Verifying certificate...
12:22:24 Status: TLS connection established.
12:22:24 Command: USER lingarddev
12:22:24 Response: 331 Username okay, awaiting password
12:22:24 Command: PASS **********
12:22:25 Response: 230 User logged in, proceed
12:22:25 Command: OPTS UTF8 ON
12:22:25 Response: 200 UTF8 encoding on
12:22:25 Command: PBSZ 0
12:22:25 Response: 200 OK
12:22:25 Command: PROT P
12:22:25 Response: 200 OK
12:22:25 Status: Logged in
12:22:25 Status: Retrieving directory listing...
12:22:25 Command: PWD
12:22:25 Response: 257 "/"
12:22:25 Command: TYPE I
12:22:25 Response: 200 Switch to "binary" transfer mode.
12:22:25 Command: PASV
12:22:25 Response: 227 PASV OK (localhost,203,33)
12:22:25 Command: PORT 127,0,0,1,196,177
12:22:25 Response: 200 The requested action has been successfully completed
12:22:25 Command: LIST
12:22:25 Response: 150 File status okay; about to open data connection
12:22:25 Response: 226 Closing data connection
12:22:25 Error: GnuTLS error -110: The TLS connection was non-properly terminated.
12:22:25 Status: Server did not properly shut down TLS connection
12:22:25 Error: Transfer connection interrupted: ECONNABORTED - Connection aborted
12:22:25 Error: Failed to retrieve directory listing
Any ideas or anyone else having success here?
Hi,
It looks like the STAT
command is actually doing LIST
's job. According to Wikipedia
LIST
returns information of a file or directorySTAT
returns information about the serverLooking to your code I saw stat.js is returning FileStat
and LIST
returns an error when you give a file as path.
To be conform to a FTP server, STAT
should return the state of the instance and LIST
should accept a file as argument and do a fs.stat()
on it.
When a user uploads a file to a dir, STOR just gives the name and not the full path, which would then require to traverse all the dirs.
It would be nice to get the full path of the file that was just uploaded
Hi Stewart,
It's really great that you added the concept of client error, I was just about to contact you about it 2 weeks ago. Without this possibility of capturing errors, the server was crashing when there were firewall issue or anormal connection breaks. Now it seems to works well. Whatever I saw that you modified a lot of code that may helped for crash issue....
While simulating connection failures I noticed that the client-error
event is triggered twice. So one for the channel command and a second time for the data channel. However, the connection.userName
property is valid in the channel command event, but for the data channel event it is undefined. Is this normal? I think the user name of a command channel connection should be preserved while opening the data channel connection.
Best regards,
Ftp Server have a listen method, but what about close? I cannot see in documentation a close method
Could you please provide a .d.ts file to support Typescript with intellisense?
Anyway, thanks for your great work on this module!
Noticed this with the new version I installed today. (2.13.1) . The previous version I was using was 2.11.4.
This works:
const FtpSrv = require('ftp-srv');
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);
This throws the following error:
const { FtpSrv, FileSystem } = require('ftp-srv');
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);
const ftpServer = new FtpSrv(config.get('ftp').url, config.get('ftp').options);
^
TypeError: FtpSrv is not a constructor
I also noticed in the README there are a few places where FtpSrv
is referenced as FtpSvr
.
Looks like ftp-srv.js
is now missing when npm installed, and the package.json main
points to src/index.js
. ftp-srv.js
is missing from the files
array in the package.json. If I put ftp-srv.js
back manually (I grabbed the one from 2.11.4) and change the package.json to point to it, it works again. I am sure the main
value was changed for a reason, but not knowing exactly why, I am hesitant to put in a PR that in essence undoes the recent changes.
Hi,
I'm having some issue with the passive mode for any operation that requires it (list, put, mkdir,...)
230 User logged in, proceed
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (X,X,X,X,35,40)
ftp: connect: Invalid argument
ftp>
I tried both methods on my FTP server and they work without flaws or timeouts.
I tried to play with the pasv port range
but without more success and I'm a bit dry on new idea to solve this. Did you experiment this? Have any idea?
Thank you
What would you think to let the user overwrite only a part of the FS ? Use case: I only want to implement the list()
method so it would return the .
folder as well.
What I would like to do:
srv.on('login', ({connection, username, password}, resolve, reject) => {
resolve({fs: {
list: function(path) {...}
});
});
Basically, this means operating a merge
here instead of an OR
.
What do you think of that? If you're ok with it I can write a PR for that.
If I started listening server always show log in command line. That would not be a problem. But if I use part of a system then it is a problem! If I set the log option to null
or false
, I get error.
I would like to have a 'slient' option.
Ubuntu 16.04 64 bits
Listing directory not works, this shows the console:
{"name":"ftp-srv","hostname":"vps0","pid":22478,"id":"318b90e8-1643-4b61-9290-72a5d554f7ce","ip":null,"directive":"LIST","level":50,"err":{"message":"timed out after 5000ms","name":"TimeoutError","stack":"TimeoutError: timed out after 5000ms\n at onTimeout (/home/kodhe/projects/ftp-server/node_modules/when/lib/decorators/timed.js:69:7)\n at Timeout._onTimeout (/home/kodhe/projects/ftp-server/node_modules/when/lib/decorators/timed.js:13:4)\n at ontimeout (timers.js:386:11)\n at tryOnTimeout (timers.js:250:5)\n at Timer.listOnTimeout (timers.js:214:5)"},"msg":"timed out after 5000ms","time":"2017-12-05T05:29:00.119Z","v":0}
Looks like require('./registration/eprt'),
is missing from src/commands/registry.js
. Without this IPv6 connections don't seem to work.
The callback to (net | tls).server.listen
will not receive an error argument, but is instead attached as a callback to the "listening" event. When there is a binding error listening
will never be dispatched and the promise is dead and will never reject nor resolve.
See https://nodejs.org/api/net.html#net_server_listen
No host is passed on to the net.server.listen()
, as such the default 0.0.0.0
is always bound.
Trying to use ftp-srv with TypeScript. Whenever I do an npm install the type definition is not included. I've been install ftp-srv v2.11.3
I am using ftp-srv in a Typescript project. When calling data.connection.on(...)
the ts compiler responds with
TS2339: Property 'on' does not exist on type 'FtpConnection'
.
A working fix is to update the type declaration in ftp-srv.d.ts
from
export class FtpConnection {...}
to
export class FtpConnection extends EventEmitter {...}
.
which is also how the actual implementation is defined.
Not sure if this is worth a PR, and also not sure how to add a test for this fix since ftp-srv is not a ts project. Let me know if you would prefer a PR anyway. Otherwise I suggest to incorporate this in the next patch.
Is there anyway to get the IP address of the user attempting to login?
Thanks ๐
I ran ftp server on Unbutu 12.04.
And I connected through chrome browser I got error.
Both firefox and ie were work fine.
Here is my server code
`const os = require('os');
const FtpSrv = require('ftp-srv');
const bunyan = require('bunyan');
const log = bunyan.createLogger({ name: '97' });
log.level('trace');
const server = new FtpSrv('ftp://168.219.244.97:21', {
anonymous: 'sillyrabbit',
log: log,
pasv_range: 8881,
greeting: ['Welcome', 'to', 'the', 'jungle!'],
tls: {
key: ${process.cwd()}/files.mysite.key
,
csr: ${process.cwd()}/files.mysite.csr
,
crt: ${process.cwd()}/files.mysite.crt
}
});
server.on('login', (data, resolve, reject) => {
if (data.username === 'anonymous') {
resolve({
root: '/home6/common/'
});
} else {
reject();
}
});
server.on('client-error', ({ connection, context, error }) => {
console.log(context);
console.log(error);
});
server.on('error', (err) => {
console.log(err);
});
server.on('uncaughtException', (err) => {
console.log(err);
})
server.listen();`
And followed log is error when I connect through Chrome.
{"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"level":10,"msg":"[ 'LIST -l' ]","time":"2017-07-05T04:35:28.656Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"directive":"LIST","level":10,"command":{"directive":"LIST","arg":"-l","raw":"LIST -l"},"msg":"Handle command","time":"2017-07-05T04:35:28.656Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"directive":"LIST","level":50,"err":{"message":"ENOENT: no such file or directory, stat '/home6/common/-l'","name":"Error","stack":"Error: ENOENT: no such file or directory, stat '/home6/common/-l'\n at Error (native)","code":"ENOENT"},"msg":"ENOENT: no such file or directory, stat '/home6/common/-l'","time":"2017-07-05T04:35:28.657Z","v":0} {"name":"97","hostname":"VDBS1485","pid":15878,"id":"99231d2a-68a7-4bd9-b3c6-b636384702ab","ip":null,"level":10,"port":21,"encoding":"utf8","packet":"451 ENOENT: no such file or directory, stat '/home6/common/-l'","msg":"Reply","time":"2017-07-05T04:35:28.657Z","v":0}
Requires AUTH
command support.
I'm having issues when trying to upload some files to ftp server when TLS is enabled:
{"name":"ftp-srv","hostname":"laptop","pid":16256,"id":"-8197-4e6d-b1f8-a944121da3d8","directive":"STOR","level":50,"err":{"message":"operation timed out","name":"TimeoutError","stack":"TimeoutError: operation timed out\n at afterTimeout (/home/jquinto/node_modules/bluebird/js/release/timers.js:46:19)\n at Timeout.timeoutTimeout [as _onTimeout] (/home/jquinto/node_modules/bluebird/js/release/timers.js:76:13)\n at ontimeout (timers.js:498:11)\n at tryOnTimeout (timers.js:323:5)\n at Timer.listOnTimeout (timers.js:290:5)"},"msg":"operation timed out","time":"2018-06-14T09:14:30.628Z","v":0}
Note: If TLS disabled that works perfectly.
My code:
const server = new FtpServer("ftps://127.0.0.1:8880", {
logger,
pasv_range: 8881,
tls: {
key: `${process.cwd()}/cert/server.key`,
cert: `${process.cwd()}/cert/server.crt`,
ca: `${process.cwd()}/cert/server.csr`
},
anonymous: true
})
server.on("login", ({ connection, username, password }, resolve, reject) => {
if ((username === "test" && password === "test") || username === "anonymous") {
connection.on("STOR", (error, fileName) => {
logger.info("file stored: ", fileName)
})
connection.on("RETR", (error, filePath) => {
logger.info("file downloaded: ", filePath)
})
resolve({ root: `${process.cwd()}/bdd/mockftp/root` })
} else reject("Bad username or password")
})
server.on("client-error", ({ error }) => {
logger.error(error)
})
server.listen().then(() => {
logger.info("started FTP service.")
})
Hi,
I connect to the server using FileZilla and then download about 100 files of (1-2K each). On half of the transfert I removed all remaining items (~50 files) from the download queue of FileZilla. After what, Filezilla seems to detect a connection break. I tried reconnecting but the server does no longer listen on that port.
netstat -anp | grep 21
Give nothing, ftp-srv crashed.
I then look on the console and then I saw this error, maybe it will help you.
Cannot read property 'write' of null","name":"TypeError","stack":"TypeError: Cannot read property 'write' of null\n
at ReadStream.stream.on.data (/root/xxx/node_modules/ftp-srv/src/commands/registration/retr.js:18:56)\n
at emitOne (events.js:96:13)\n
at ReadStream.emit (events.js:188:7)\n
at readableAddChunk (_stream_readable.js:176:18)\n
at onread (fs.js:2018:12)\n
at FSReqWrap.wrapper [as oncomplete] (fs.js:683:17)
I'm using the latest version : ftp-srv : 2.11.2
Typing ftp-srv ftp://0.0.0.0:9876 --root ~/Documents
will print Unhandled rejection Error: listen EACCES 127.0.0.1:21
: it should listen to port 9876
, not 21
.
Is this a bug? Am I doing something wrong here?
The "this.emit('STOR', null, fileName)" line at store.js:46 is called but it never gets to my code. The file is uploaded.
const ftpServer = new FtpSvr(
'ftp://' + ip.address().toString() + ':3000', {
anonymous: false,
pasv_range: '8000-9000',
greeting: 'xxx-FTP'
}
);
ftpServer
.listen()
.then(() => {
gc.log(`started FTP service ${ip.address().toString()}`);
});
ftpServer
.on('login', ({
connection, // eslint-disable-line no-unused-vars
username, password }, resolve, reject) => {
if (username === 'xxx' && password === 'xxxxx')
resolve({ root: './data/'});
else
reject({ root: './data/anonymous' });
});
ftpServer.on('STOR', (error, fileName) => {
if (error) console.log(error);
else console.log(fileName);
});`
`
When I try to do actions on the ftp server, I always get an error in the console from fs.
Here's the error (I replaced sensitive data with HIDDEN):
{"name":"ftp-srv","hostname":"HIDDEN","pid":7824,"id":"c9371611-e73c-4b70-a42b-1745957d6418","directive":"CWD","level":50,"err":{"message":"Not a valid directory","name":"FileSystemError","stack":"FileSystemError: Not a valid directory\n at fs.statAsync.tap.stat (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\ftp-srv\2.16.1\node_modules\ftp-srv\src\fs.js:58:38)\n at PassThroughHandlerContext.finallyHandler (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\finally.js:57:23)\n at PassThroughHandlerContext.tryCatcher (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\util.js:16:23)\n at Promise._settlePromiseFromHandler (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:512:31)\n at Promise._settlePromise (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:569:18)\n at Promise._settlePromise0 (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:614:10)\n at Promise._settlePromises (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:693:18)\n at Promise._fulfill (C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\promise.js:638:18)\n at C:\HIDDEN\ftpserver\node_modules\.registry.npmjs.org\bluebird\3.5.1\node_modules\bluebird\js\release\nodeback.js:42:21\n at FSReqWrap.oncomplete (fs.js:171:5)","code":400},"msg":"Not a valid directory","time":"2018-04-23T17:43:13.827Z","v":0}
Here's my code:
require('dotenv').load()
const ftpsrv = require('ftp-srv'),
fs = require('fs')
const server = new ftpsrv(`ftp://127.0.0.1:${process.env.PORT || 7777}`)
server.on('login', (user, resolve, reject) => {
if (user.username === 'siffrein' && user.password === 'HIDDEN') {
resolve({ root: process.cwd() + '/public/' })
} else reject('Bad username or password.')
})
server.listen()
The error occurs when I connect, when I manipulate files, ...
I'm on Windows 10 build 1803 with pnpm 1.40.2, npm 5.6.0, node 9.11.2 and the latest WinSCP. I tried with both pnpm and npm.
I had problems at first with node-gyp and dtrace-provider.
Can someone give me an code example how to set up tls on ftp? Do I need the node tls package?
Currently the errors classes from errors.js
are not available for external use.
It would be great to expose them in case anyone wants to override the filesystem and use those errors as well.
This happens with both the CLI and servers created via the API.
Launch the CLI:
> ftp-srv ftp://localhost:9876 --root ~/work/ftpsrv/ --username
Then try to GET any file that starts with a hyphen -
$ ftp anonymous@localhost 9876
ftp> get -foo
remote: -foo
Expected behavior: If there's a file named -foo
, it should 150 File status okay; about to open data connection
. If no such file exists, it should respond with 551 ENOENT: no such file or directory
Actual behavior: On the server:
Unhandled rejection TypeError: Path must be a string. Received null
at assertPath (path.js:28:11)
at Object.normalize (path.js:1202:5)
at serverPath (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:21:23)
at FileSystem._resolvePath (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:27:7)
at FileSystem.get (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/fs.js:45:27)
at FtpConnection.handler (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/commands/registration/size.js:9:36)
at FtpCommands.handle (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/commands/index.js:65:28)
at Promise.mapSeries.message (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/connection.js:44:65)
From previous event:
at FtpConnection._handleData (/Users/kieffer/work/ftpsrv/node_modules/ftp-srv/src/connection.js:44:20)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:607:20)
I use this great project to run a server to test my library https://github.com/simonh1000/ftp-deploy
I've recently switched to mac and I can get the server to start and register a login, but it seems to do no more than that - no greeting is received by my client (filezilla) nor any directory listing. I'm looking for ideas on fixing this, and after reading lots of articles that MacOS rather nixed ftp with High Sierra
const homeDir =
require("os").homedir() + "/code/sync/nodejs/ftp-deploy/test/remote/";
const FtpSrv = require("ftp-srv");
const options = {
greeting: ["test ftp server", homeDir],
anonymous: true
};
// Using non-standard port
const port = 2121;
const ftpServer = new FtpSrv("ftp://0.0.0.0:" + port, options);
ftpServer.on('login', (data, resolve, reject) => {
console.log("[login] Connection by", data);
console.log("[login] Setting home dir to:", homeDir);
resolve({ root: homeDir });
});
ftpServer
.listen()
.then(() => {
console.log(`Serving ${homeDir} on port: ${port}`);
})
.catch(err => {
console.log("[error]", err);
});
This is the error I currently get
username: 'anonymous',
password: '@anonymous' }
[login] Setting home dir to: /code/sync/nodejs/ftp-deploy/test/remote/
{"name":"ftp-srv","hostname":"xxxxx.home","pid":91037,"id":"ebcbfc41-1795-4185-80a8-aed84c5f066c","directive":"LIST","level":50,"err":{"message":"operation timed out","name":"TimeoutError","stack":"TimeoutError: operation timed out\n at afterTimeout (/code/sync/nodejs/ftp-deploy/node_modules/bluebird/js/release/timers.js:46:19)\n at Timeout.timeoutTimeout [as _onTimeout] /code/sync/nodejs/ftp-deploy/node_modules/bluebird/js/release/timers.js:76:13)\n at ontimeout (timers.js:425:11)\n at tryOnTimeout (timers.js:289:5)\n at listOnTimeout (timers.js:252:5)\n at Timer.processTimers (timers.js:212:10)"},"msg":"operation timed out","time":"2018-12-03T20:54:19.594Z","v":0}
The current CONTRIBUTING.md was auto-generated using confit.
This should be updated to reflect the standards and practices for this repo.
Hi,
I'm having issues installing this inside a virtual machine (Ubuntu server), inside a shared folder (from Windows 7).
I think this is a common issue with modules that require compiling binaries.
Something related to symlinks.
I get some ENOENT warnings tar ENOENT: no such file or directory, lstat...
, then an ENOENT error.
Hi,
When calling STAT
on a file, I get a response with an incorrect format: a number then a space then the stat infos.
I first thought it was a client problem (see sergi/parse-listing#13) but it looks like the protocol standard align with the client.
I think something's wrong here https://github.com/trs/ftp-srv/blob/master/src/commands/registration/stat.js#L31 but I don't know what nor why.
Could you lead me to a solution? Thanks
I'm running this code on Windows and keep getting an error
Disconnected from server: ECONNABORTED - Connection aborted
Using FileZilla
_Status: Connecting to 127.0.0.1:21...
Status: Connection established, waiting for welcome message...
Status: Logged in
Status: Retrieving directory listing...
Command: PWD
Response: 257 "\"
Command: TYPE I
Response: 200 Switch to "binary" transfer mode.
Command: PASV
Error: Disconnected from server: ECONNABORTED - Connection aborted
Error: Failed to retrieve directory listing_
var ftp = require('ftp-srv');
var fs = require('fs')
var path = require('path')
var ftpd = new ftp('ftp://0.0.0.0:21', {
root: path.join(__dirname, 'public'),
anonymous: true
});
ftpd.on('login', (user, resolve, reject) => {
resolve({ root: path.join(__dirname, 'public') })
});
ftpd.listen()
Is my code wrong?
Hi there!
Using ftp-srv
on a project and I am getting this error:
ftpServer.on('client-error', (data) => {
// data.context
context:"dataServer"
// data.error
address:"192.168.0.120"
code:"EADDRINUSE"
errno:"EADDRINUSE"
port:8080
syscall:"listen"
});
I have 2 CCTV cameras that FTP snapshots of CCTV Footage to ftp-srv
every second. This is not a persistent error, it just happens every now and then, maybe once every few seconds? But every time it happens, there is a 10 second gap for ftp-srv to recover. I really can't pinpoint when or why this is happening though. Tried googling, failed.
Here is the bulk of the code, if it helps:
const ftpServer = new FtpSrv('ftp://192.168.0.120:9876', {
pasv_range:8080
});
ftpServer.on('login', (data, resolve, reject) => {
resolve({root: 'F:/path/to/ftp/root'});
data.connection.on('STOR', (error, fileName) => {
var filePath = data.connection.fs.cwd;
if (error === null) {
mainWindow.webContents.send('cctvSnapshot', {
filePath: filePath,
fileName: fileName
});
}
});
});
Any idea how to fix this?
Is there a way for setting the root dir using js code? There is nothing in the documentation about this, and it appears to use to current working directory instead of the directory I set, when I start the server with node this way:
const FtpSrv = require('ftp-srv');
const path = require("path");
const root = path.join(__dirname, "ftp");
const ftpServer = new FtpSrv('ftp://0.0.0.0:9876', {root: root, anonymous: true});
ftpServer.listen();
I'm using this ftp server on my android box using Termux.
Using the LAN, my ftp server works great. But when I'm accessing from outside of my LAN it doesn't work. I got the message Socket couldn't write, but all my permissions of files and directories are 777, and I think that I got an 5000ms timeout error once in the past.
One thing to note is that my ls
it is not on /bin/ls
but it is on /data/data/com.termux/files/usr/bin/ls
.
So here it is my program:
process.chdir(__dirname);
const FtpSvr = require('ftp-srv');
const ftpServer = new FtpSvr('ftp://0.0.0.0:3000', {anonymous: true, pasv_range: 8000});
ftpServer.on('login', ({connection, username, password}, resolve, reject) => {
if(username === 'daniel' && password === 'ola') {
resolve({root: './data/'});
} else {
resolve({root: './data/anonymous'});
}
});
ftpServer.listen();
and here is an image of an outside test of my server using https://ftptest.net/:
Can someone help me?
Uncaught TypeError: types.isModuleNamespaceObject is not a function
at formatValue (util.js:664:22)
at Object.inspect (util.js:328:10)
at Logger.addStream (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:581:62)
at new Logger (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:490:18)
at Function.createLogger (C:\Users\123\bpnex\node_modules\bunyan\lib\bunyan.js:1618:12)
at new FtpServer (C:\Users\123\bpnex\node_modules\ftp-srv\src\index.js:17:18)
In the stor.js file, line 33:
.finally(() => when.try(stream.destroy.bind(stream)));
This line attempts to call destroy on the writable stream (the class stream.Writable has no destroy method) returned from the FileSystem.write method. I suspect this should be against the data socket like so:
.finally(() => when.try(dataSocket.destroy.bind(dataSocket)));
Edit: To clarify I'm using a Duplex PassThrough stream for which destroy is not defined. I see now that the Writable stream has a non-public destroy method. It doesn't look like the Duplex stream implements that until an update added in May (not in the version I have).
If this is intended to called be on the writable stream, I can shim it for the time being.
I'd like to run $ ftp-srv as I run http-server, from CLI. Is that possible? I could work on this if it makes sense. Let me know.
Hi,
I'm having problem setting the ftp root folder on Windows. Here is what I did :
const ftp_srv = require('ftp-srv');
const f = new ftp_srv("127.0.0.1:21", {});
f.on('login', ({ username, password }, resolveLogin, rejectLogin) => {
return resolveLogin({
root: "d:\\ftp_root",
cwd: "/"
});
)};
f.listen();
When the client is getting the file (LIST) the here is what I'm getting in fs.js
class FileSystem {
constructor(connection, {
root = '/',
cwd = '/'
} = {}) {
this.connection = connection;
this.cwd = nodePath.resolve(cwd); // "/" = "d:/"
this.root = nodePath.resolve(root); // "d:\\ftp_root" = "d:\ftp_root"
}
Now in the list
function :
list(path = '.') {
path = this._resolvePath(path); // path = "d:\ftp_rootd:\"
return fs.readdir(path)
.then(fileNames => {
Thus, d:\ftp_rootd:\
is not a valid folder on my host. Why the cmd
and the root
folder are merge together ? Why not use only the root
argument ?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.