feat(FTP Node): Add support for concurrent reads when using SFTP (#17896)

Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Michael Kret <michael.k@radency.com>
This commit is contained in:
Jon
2025-08-04 12:40:18 +01:00
committed by GitHub
parent 508c636c2c
commit e437dace70
3 changed files with 94 additions and 18 deletions

View File

@@ -289,7 +289,50 @@ export class Ftp implements INodeType {
hint: 'The name of the output binary field to put the file in',
required: true,
},
{
displayName: 'Options',
name: 'options',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
operation: ['download'],
},
},
options: [
{
displayName: 'Enable Concurrent Reads',
name: 'enableConcurrentReads',
type: 'boolean',
default: false,
description: 'Whether to enable concurrent reads for downloading files',
},
{
displayName: 'Max Concurrent Reads',
name: 'maxConcurrentReads',
type: 'number',
default: 5,
displayOptions: {
show: {
enableConcurrentReads: [true],
},
},
},
{
displayName: 'Chunk Size',
name: 'chunkSize',
type: 'number',
default: 64,
description: 'Size of each chunk in KB to download, Not all servers support this',
displayOptions: {
show: {
enableConcurrentReads: [true],
},
},
},
],
},
// ----------------------------------
// rename
// ----------------------------------
@@ -530,6 +573,10 @@ export class Ftp implements INodeType {
password: (credentials.password as string) || undefined,
privateKey: formatPrivateKey(credentials.privateKey as string),
passphrase: credentials.passphrase as string | undefined,
readyTimeout: 10000,
algorithms: {
compress: ['zlib@openssh.com', 'zlib', 'none'],
},
});
} else {
await sftp.connect({
@@ -537,6 +584,10 @@ export class Ftp implements INodeType {
port: credentials.port as number,
username: credentials.username as string,
password: credentials.password as string,
readyTimeout: 10000,
algorithms: {
compress: ['zlib@openssh.com', 'zlib', 'none'],
},
});
}
} else {
@@ -632,9 +683,21 @@ export class Ftp implements INodeType {
if (operation === 'download') {
const path = this.getNodeParameter('path', i) as string;
const options = this.getNodeParameter('options', i);
const binaryFile = await tmpFile({ prefix: 'n8n-sftp-' });
try {
await sftp!.get(path, createWriteStream(binaryFile.path));
if (!options.enableConcurrentReads) {
await sftp!.get(path, createWriteStream(binaryFile.path));
} else {
await sftp!.fastGet(path, binaryFile.path, {
concurrency:
options.maxConcurrentReads === undefined
? 5
: Number(options.maxConcurrentReads),
chunkSize:
(options.chunkSize === undefined ? 64 : Number(options.chunkSize)) * 1024,
});
}
const dataPropertyNameDownload = this.getNodeParameter('binaryPropertyName', i);
const remoteFilePath = this.getNodeParameter('path', i) as string;

View File

@@ -871,7 +871,7 @@
"@types/rfc2047": "^2.0.1",
"@types/sanitize-html": "^2.11.0",
"@types/showdown": "^1.9.4",
"@types/ssh2-sftp-client": "^5.1.0",
"@types/ssh2-sftp-client": "^9.0.5",
"@types/uuid": "catalog:",
"@types/xml2js": "catalog:",
"eslint-plugin-n8n-nodes-base": "^1.16.3",
@@ -943,7 +943,7 @@
"showdown": "2.1.0",
"simple-git": "3.17.0",
"snowflake-sdk": "2.1.0",
"ssh2-sftp-client": "7.2.3",
"ssh2-sftp-client": "12.0.1",
"tmp-promise": "3.0.3",
"ts-ics": "1.2.2",
"uuid": "catalog:",

41
pnpm-lock.yaml generated
View File

@@ -2905,8 +2905,8 @@ importers:
specifier: 2.1.0
version: 2.1.0(asn1.js@5.4.1)(encoding@0.1.13)
ssh2-sftp-client:
specifier: 7.2.3
version: 7.2.3
specifier: 12.0.1
version: 12.0.1
tmp-promise:
specifier: 3.0.3
version: 3.0.3
@@ -2990,8 +2990,8 @@ importers:
specifier: ^1.9.4
version: 1.9.4
'@types/ssh2-sftp-client':
specifier: ^5.1.0
version: 5.3.2
specifier: ^9.0.5
version: 9.0.5
'@types/uuid':
specifier: 'catalog:'
version: 10.0.0
@@ -7389,8 +7389,8 @@ packages:
'@types/sizzle@2.3.3':
resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==}
'@types/ssh2-sftp-client@5.3.2':
resolution: {integrity: sha512-s5R3hsnI3/7Ar57LG++gm2kxgONHtOZY2A3AgGzEwiJlHR8j7MRPDw1n/hG6oMnOUJ4zuoLNtDXgDfmmxV4lDA==}
'@types/ssh2-sftp-client@9.0.5':
resolution: {integrity: sha512-cpUO6okDusnfLw2hnmaBiomlSchIWNVcCdpywLRsg/h9Q1TTiUSrzhkn5sJeeyTM8h6xRbZEZZjgWtUXFDogHg==}
'@types/ssh2-streams@0.1.12':
resolution: {integrity: sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==}
@@ -14617,14 +14617,18 @@ packages:
ssh-remote-port-forward@1.0.4:
resolution: {integrity: sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==}
ssh2-sftp-client@7.2.3:
resolution: {integrity: sha512-Bmq4Uewu3e0XOwu5bnPbiS5KRQYv+dff5H6+85V4GZrPrt0Fkt1nUH+uXanyAkoNxUpzjnAPEEoLdOaBO9c3xw==}
engines: {node: '>=10.24.1'}
ssh2-sftp-client@12.0.1:
resolution: {integrity: sha512-ICJ1L2PmBel2Q2ctbyxzTFZCPKSHYYD6s2TFZv7NXmZDrDNGk8lHBb/SK2WgXLMXNANH78qoumeJzxlWZqSqWg==}
engines: {node: '>=18.20.4'}
ssh2@1.15.0:
resolution: {integrity: sha512-C0PHgX4h6lBxYx7hcXwu3QWdh4tg6tZZsTfXcdvc5caW/EMxaB4H9dWsl7qk+F7LAW762hp8VbXOX7x4xUYvEw==}
engines: {node: '>=10.16.0'}
ssh2@1.16.0:
resolution: {integrity: sha512-r1X4KsBGedJqo7h8F5c4Ybpcr5RjyP+aWIG007uBPRjmdQWfEiVLzSK71Zji1B9sKxwaCvD8y8cwSkYrlLiRRg==}
engines: {node: '>=10.16.0'}
sshpk@1.18.0:
resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==}
engines: {node: '>=0.10.0'}
@@ -21952,7 +21956,7 @@ snapshots:
'@types/sizzle@2.3.3': {}
'@types/ssh2-sftp-client@5.3.2':
'@types/ssh2-sftp-client@9.0.5':
dependencies:
'@types/ssh2': 1.11.6
@@ -24854,7 +24858,8 @@ snapshots:
transitivePeerDependencies:
- ts-toolbelt
err-code@2.0.3: {}
err-code@2.0.3:
optional: true
error-ex@1.3.2:
dependencies:
@@ -29817,6 +29822,7 @@ snapshots:
dependencies:
err-code: 2.0.3
retry: 0.12.0
optional: true
promise@7.3.1:
dependencies:
@@ -31012,11 +31018,10 @@ snapshots:
'@types/ssh2': 0.5.52
ssh2: 1.15.0
ssh2-sftp-client@7.2.3:
ssh2-sftp-client@12.0.1:
dependencies:
concat-stream: 2.0.0
promise-retry: 2.0.1
ssh2: 1.15.0
ssh2: 1.16.0
ssh2@1.15.0:
dependencies:
@@ -31026,6 +31031,14 @@ snapshots:
cpu-features: 0.0.10
nan: 2.20.0
ssh2@1.16.0:
dependencies:
asn1: 0.2.6
bcrypt-pbkdf: 1.0.2
optionalDependencies:
cpu-features: 0.0.10
nan: 2.20.0
sshpk@1.18.0:
dependencies:
asn1: 0.2.6