Node.jsを使ったSFTPへの「接続」、「ファイルのリストアップ」、「アップロード」、「ダウンロード」のやり方をここで学んでみましょう。

この記事を読み終わる頃には、 みなさんは最終的にNode.jsのコードの記述に慣れてSFTP サーバーに接続してやりとりが可能になり、我々のヘルプは要らなくなるでしょう。SFTP は広く使用される標準的なプロトコルであり、ファイルやデータの安全な転送に焦点を当てた安全なプロトコルですが、サーバーとの接続を設定する際に、いくつかのステップを完了させなければいけません。では、いきますよ!

必要事項

初めの一歩:ssh2-sftp-clientは node.js 用の SFTP クライアントで、SSH2 のラッパー(wrapper)として SFTP 関連の機能を高度に抽象化したものです。インストールする準備ができたら、まず以下のコードを手動で実行します:

npm install ssh2-sftp-client@^8.0.0

またはpackage.jsonファイルを追加し、その中で依存関係を宣言します:

そして、以下を実行します:

{
  "dependencies": {
    "ssh2-sftp-client": "^8.0.0"
  }
}

そして、以下を実行します:

npm install

SFTPへの接続

この記事の例として、SFTPTOGO_URL という環境変数を使います。この環境変数には、SFTP サーバーに接続するために必要なすべての情報が、次のようなURI 形式で含まれています: sftp://user:password@host. この変数は URI.parse を使って URI の部分を抽出し、リモートサーバーのホストキーは~/.ssh/known_hostsを使ってデフォルトで検証されます。

let Client = require('ssh2-sftp-client');

class SFTPClient {
  constructor() {
    this.client = new Client();
  }

  async connect(options) {
    console.log(`Connecting to ${options.host}:${options.port}`);
    try {
      await this.client.connect(options);
    } catch (err) {
      console.log('Failed to connect:', err);
    }
  }

  async disconnect() {
    await this.client.end();
  }

}

ファイルの一覧表示

接続が確立されると、リモート SFTP サーバ上のファイルを一覧表示するのにそれを使うことができます。これは、ssh2-sftp-client の list メソッドを呼び出して返される配列を反復処理することで、path 引数で見つかったファイルに対応することができます。この例では、ラッパー関数がリモートパスで見つかったファイルを単純に出力しています。

async listFiles(remoteDir, fileGlob) {
  console.log(`Listing ${remoteDir} ...`);
  let fileObjects;
  try {
    fileObjects = await this.client.list(remoteDir, fileGlob);
  } catch (err) {
    console.log('Listing failed:', err);
  }

  const fileNames = [];

  for (const file of fileObjects) {
    if (file.type === 'd') {
      console.log(`${new Date(file.modifyTime).toISOString()} PRE ${file.name}`);
    } else {
      console.log(`${new Date(file.modifyTime).toISOString()} ${file.size} ${file.name}`);
    }

    fileNames.push(file.name);
  }

  return fileNames;
}
listfiles.js

ファイルのアップロード

次のステップは、ファイルのアップロードです。クライアントオブジェクトのput 関数を使用して、ローカルファイルのパスとリモートパスを渡します (アップロード後にファイルもリモートパスに置かれるはずです)。関数呼び出しは次のようになります:  await client.uploadFile("./local.txt", "./remote.txt");

async uploadFile(localFile, remoteFile) {
  console.log(`Uploading ${localFile} to ${remoteFile} ...`);
  try {
    await this.client.put(localFile, remoteFile);
  } catch (err) {
    console.error('Uploading failed:', err);
  }
}
uploadfile.js

ファイルのダウンロード

プロセスの締めは、ファイルのダウンロードです。クライアントオブジェクトのget関数を使い、リモートファイルのパスと、ダウンロードしたファイルを格納するローカルパスを渡します。これは、次のように関数を呼び出すことになります:await client.downloadFile("./remote.txt", "./download.txt");

async downloadFile(remoteFile, localFile) {
  console.log(`Downloading ${remoteFile} to ${localFile} ...`);
  try {
    await this.client.get(remoteFile, localFile);
  } catch (err) {
    console.error('Downloading failed:', err);
  }
}
downloadfile.js

全体像

以上の手順を踏まえて、プロセスは完了です! 最後に、プログラムを最初から最後まで通して実行したい場合は、次のコードをコピーしてmain.jsとして保存してください:

// sftp.js
//
// Use this sample code to connect to your SFTP To Go server and run some file operations using Node.js.
//
// 1) Paste this code into a new file (sftp.js)
//
// 2) Install dependencies
//   npm install ssh2-sftp-client@^8.0.0
//
// 3) Run the script
//   node sftp.js
// 
// Compatible with Node.js >= v12
// Using ssh2-sftp-client v8.0.0

let Client = require('ssh2-sftp-client');

class SFTPClient {
  constructor() {
    this.client = new Client();
  }

  async connect(options) {
    console.log(`Connecting to ${options.host}:${options.port}`);
    try {
      await this.client.connect(options);
    } catch (err) {
      console.log('Failed to connect:', err);
    }
  }

  async disconnect() {
    await this.client.end();
  }

  async listFiles(remoteDir, fileGlob) {
    console.log(`Listing ${remoteDir} ...`);
    let fileObjects;
    try {
      fileObjects = await this.client.list(remoteDir, fileGlob);
    } catch (err) {
      console.log('Listing failed:', err);
    }

    const fileNames = [];

    for (const file of fileObjects) {
      if (file.type === 'd') {
        console.log(`${new Date(file.modifyTime).toISOString()} PRE ${file.name}`);
      } else {
        console.log(`${new Date(file.modifyTime).toISOString()} ${file.size} ${file.name}`);
      }

      fileNames.push(file.name);
    }

    return fileNames;
  }

  async uploadFile(localFile, remoteFile) {
    console.log(`Uploading ${localFile} to ${remoteFile} ...`);
    try {
      await this.client.put(localFile, remoteFile);
    } catch (err) {
      console.error('Uploading failed:', err);
    }
  }

  async downloadFile(remoteFile, localFile) {
    console.log(`Downloading ${remoteFile} to ${localFile} ...`);
    try {
      await this.client.get(remoteFile, localFile);
    } catch (err) {
      console.error('Downloading failed:', err);
    }
  }

  async deleteFile(remoteFile) {
    console.log(`Deleting ${remoteFile}`);
    try {
      await this.client.delete(remoteFile);
    } catch (err) {
      console.error('Deleting failed:', err);
    }
  }
}

(async () => {
  const parsedURL = new URL(process.env.SFTPTOGO_URL);
  const port = parsedURL.port || 22;
  const { host, username, password } = parsedURL;

  //* Open the connection
  const client = new SFTPClient();
  await client.connect({ host, port, username, password });

  //* List working directory files
  await client.listFiles(".");

  //* Upload local file to remote file
  await client.uploadFile("./local.txt", "./remote.txt");

  //* Download remote file to local file
  await client.downloadFile("./remote.txt", "./download.txt");

  //* Delete remote file
  await client.deleteFile("./remote.txt");

  //* Close the connection
  await client.disconnect();
})();
main.js

最後に、コマンドで実行します:

node main.js

やりました!Node.jsを使ったSFTPへの接続ができました!

SFTP To Go with maximum security and reliability
SFTP To Go offers managed SFTP/FTPS/S3 as a service - maximum reliability, security, availability, with 1 minute setup. Great for companies of any size, any scale.
Check out SFTP To Go!

その他コードサンプルはGithubでご覧ください。