Last active
May 17, 2020 04:54
-
-
Save deskoh/b92316a6251c60ebad05a8448d32b0c1 to your computer and use it in GitHub Desktop.
SFTP Client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const crypto = require('crypto'); | |
| const fs = require('fs'); | |
| const path = require('path'); | |
| const Client = require('ssh2-sftp-client'); | |
| // Host public key e.g. /etc/ssh/ssh_host_ecdsa_key.pub | |
| const fingerprint = process.env.HOST_FINGERPRINT; | |
| const hostConfig = { | |
| host: process.env.HOST, | |
| port: process.env.PORT || 22, | |
| username: process.env.USER, | |
| privateKey: process.env.KEY, | |
| hostHash: 'md5', | |
| hostVerifier: (keyHash) => serverHash === keyHash, | |
| }; | |
| const serverHash = hostHash(fingerprint, 'md5'); | |
| async function main() { | |
| try { | |
| let client = new Client(); | |
| await client.connect(hostConfig) | |
| console.log('Connected to', hostConfig.host); | |
| const dir = '/sftpuser'; | |
| const files = await client.list(dir); | |
| const downloadList = files.filter(f => f.name.endsWith('.txt')).map(f => `${dir}/${f.name}`); | |
| await downloadFiles(client, downloadList); | |
| await client.end(); | |
| console.log('Connection closed'); | |
| } catch (error) { | |
| console.log(error, 'catch error'); | |
| } | |
| } | |
| function hostHash(fingerprint, algorithm) { | |
| const key = Buffer.from(fingerprint, 'base64'); | |
| var hasher = crypto.createHash(algorithm); | |
| hasher.update(key); | |
| return hasher.digest('hex'); | |
| } | |
| async function downloadFiles(client, downloadList) { | |
| const downloadFileAsync = async (f) => { | |
| try { | |
| process.stdout.write(`Downloading ${f}...`); | |
| const buffer = await retry(client.get(f)); | |
| fs.writeFileSync(`T:/${path.basename(f)}`, buffer); | |
| console.log('Done'); | |
| process.stdout.write(`Writing acknowledgement for ${f}...`); | |
| const ackFile = `${path.dirname(f)}/${path.basename(f, '.txt')}.ack`; | |
| await retry(client.put(Buffer.from('OK\n', 'utf-8'), ackFile)); | |
| console.log('Done'); | |
| process.stdout.write(`Deleting ${f}...`); | |
| await retry(client.delete(f)); | |
| console.log('Done'); | |
| } catch (error) { | |
| console.error(`Failed to process ${f}`, error); | |
| } | |
| } | |
| return downloadList.reduce(async (prevPromise, nextFile) => { | |
| await prevPromise; | |
| return downloadFileAsync(nextFile); | |
| }, Promise.resolve()); | |
| } | |
| function retry(promise, retries=3, err=null) { | |
| if (!retries) { | |
| return Promise.reject(err); | |
| } | |
| return promise.catch(err => { | |
| console.error(err); | |
| console.log('Error occurred. Retrying...'); | |
| return retry(promise, (retries - 1), err); | |
| }); | |
| } | |
| main(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment