コンテンツにスキップ

transfer

MODULES.transferは、Craft Functionsから外部サーバーへファイルを転送するモジュールです。HTMLだけでなく、CSV・JSON・画像なども扱えます。

メソッド操作SCPSFTP
writeFile文字列またはBufferをファイルに書き込みます。対応対応
renameファイルを移動し、既存の移動先を原子的に置き換えます。非対応POSIX rename拡張が必要
removeファイルを1つ削除します。非対応対応

各メソッドは独立して接続・切断します。接続を管理するためのconnectやcloseを呼び出す必要はありません。

各メソッドのconnectionに次のオブジェクトを渡します。

プロパティ型必須説明
hoststring必須接続先のホスト名です。
portnumber任意接続先ポートです。省略時は22です。1〜65535の整数を指定します。
usernamestring必須接続先のユーザー名です。
protocolstring必須'scp'または'sftp'を指定します。自動的な切り替えは行いません。
passwordstring認証方式によるパスワード認証に使用します。
privateKeystring認証方式による秘密鍵の内容を指定します。鍵ファイルのパスは指定できません。
passphrasestring任意暗号化された秘密鍵のパスフレーズです。privateKeyと併せて指定します。
hostKeySha256string任意接続先のホスト鍵のSHA-256フィンガープリントです。

passwordとprivateKeyは、どちらか一方だけを指定してください。上記以外の接続オプションは指定できません。

hostKeySha256を指定すると、サーバーのホスト鍵が一致する場合だけ接続します。接続先管理者から信頼できる経路で取得した、SHA256:に続く43文字のBase64形式(末尾の=なし)を指定してください。

省略時はホスト鍵を検証しません。通信は暗号化されますが、接続先のなりすましは検知できません。省略する場合は、空文字やnullを渡さず、プロパティ自体を省略してください。

  • 公開IPv4アドレスへの接続に対応します。localhost、プライベートネットワーク、リンクローカル、その他の特殊用途・予約済みアドレスには接続できません。
  • ホスト名の名前解決結果に接続を許可しないIPv4アドレスが含まれる場合も接続できません。
  • IPv6には対応していません。
  • リモートOSはPOSIXを対象としています。操作に必要な権限を持つアカウントと、作成済みの配置先ディレクトリを用意してください。

あらかじめCraft Secret ManagerにSFTP_HOST、SFTP_USERNAME、SFTP_PASSWORDを保存してください。次の例は、接続先の/uploadsディレクトリにCSVを書き込みます。

export default async function (data, { MODULES }) {
const secrets = await MODULES.secret.get({
keys: ['SFTP_HOST', 'SFTP_USERNAME', 'SFTP_PASSWORD'],
});
const connection = {
host: secrets.SFTP_HOST,
username: secrets.SFTP_USERNAME,
password: secrets.SFTP_PASSWORD,
protocol: 'sftp',
// ホスト鍵を検証する場合はhostKeySha256も指定します。
};
const result = await MODULES.transfer.writeFile({
connection,
remotePath: '/uploads/export.csv',
content: 'id,name\n1,example\n',
});
return result;
}

接続設定の取得はユーザーコードで行います。transferモジュールが内部でSecretを取得することはありません。

const result = await MODULES.transfer.writeFile({
connection,
remotePath: '/uploads/export.csv',
content: 'id,name\n1,example\n',
});
// result: { remotePath: '/uploads/export.csv', bytes: 18 }
パラメーター型説明
connectionobject接続設定です。SCPまたはSFTPを指定します。
remotePathstring接続先での配置先の絶対パスです。
contentstring または Buffer書き込むデータです。最大5 MiB(5,242,880バイト)です。

文字列はUTF-8、Bufferはそのままのバイト列で転送します。戻り値は配置先のremotePathと転送バイト数のbytesです。

既存ファイルには直接上書きします。書き込み中のファイルを参照すると、途中までの内容を読み取る場合があります。書き込みに失敗すると、空のファイルや途中までの内容が残る場合もあります。新規ファイルのモードは0644です。

バイナリデータは、例えば次のように渡します。

await MODULES.transfer.writeFile({
connection,
remotePath: '/uploads/logo.png',
content: Buffer.from(base64Image, 'base64'),
});

contentにローカルファイルのパスを渡しても、ファイルは読み取りません。パスの文字列自体を書き込みます。Streamは受け付けません。

await MODULES.transfer.rename({
connection,
from: '/uploads/index.html.tmp',
to: '/uploads/index.html',
});

connection.protocolには'sftp'を指定します。fromとtoはそれぞれ移動元と移動先の絶対パスです。完了時の戻り値はありません。

同一ファイルシステム内で使用してください。既存の移動先ファイルを原子的に置き換えるため、公開先で書き込み途中の内容が参照されることを避けられます。

一時ファイルを書き込んでから公開する例

Section titled “一時ファイルを書き込んでから公開する例”

以下は、上記の例と同様に用意したconnectionを使用します。protocolは'sftp'にしてください。

const id = `${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
const temporaryPath = `/uploads/index-${id}.html.tmp`;
const publishedPath = '/uploads/index.html';
await MODULES.transfer.writeFile({
connection,
remotePath: temporaryPath,
content: '<!doctype html><html><body>更新しました</body></html>',
});
await MODULES.transfer.rename({
connection,
from: temporaryPath,
to: publishedPath,
});

一時パスの生成、失敗時の削除、同じ公開先への更新順序の制御はユーザーコードで行ってください。renameに失敗しても、一時ファイルは自動で削除されません。

SCPで書き込んだ後にSFTPで移動する場合は、renameにconnection: { ...connection, protocol: 'sftp' }を渡します。接続先は両方のプロトコルとPOSIX rename拡張に対応し、同じファイルを操作できる必要があります。

await MODULES.transfer.remove({
connection,
remotePath: '/uploads/index.html.tmp',
});

connection.protocolには'sftp'を指定します。remotePathは削除するファイルの絶対パスです。完了時の戻り値はありません。

対象が存在しない場合も成功します。権限不足などのエラーでは失敗します。ディレクトリの再帰的な削除には対応していません。

  • パスは最大4096文字の絶対パスで指定します。各ディレクトリ名・ファイル名は英数字または_で始まり、英数字・_・-・.のみ使用できます。日本語・空白・..による親ディレクトリ指定は利用できません。
  • ファイルの拡張子に制限はありません。親ディレクトリを自動作成する機能はありません。
  • 各操作の名前解決・接続・転送などは合計30秒でタイムアウトします。Secretの取得時間は含みません。ファンクション全体のタイムアウトにも余裕を持たせてください。
  • 通信が途切れた場合などは、エラーになってもサーバー側で操作が完了している可能性があります。自動リトライは行いません。
  • ファイルの内容は変更しません。CMSの値をHTMLに埋め込む際のエスケープなどはユーザーコードで行ってください。

入力値が不正な場合は、Invalid transfer connection settingsやInvalid remotePathなどのエラーになります。接続・操作中の失敗は、判別できた原因に応じて次のようなメッセージになります。

メッセージ確認する項目
File transfer failed: authentication failedユーザー名、パスワード、秘密鍵などの認証設定
File transfer failed: permission denied接続先アカウントの操作権限
File transfer failed: remote file not found対象ファイルや親ディレクトリの有無
File transfer failed: SFTP unavailable接続先のSFTP対応状況
File transfer failed: destination not allowed (public IPv4 required)接続先が公開IPv4アドレスかどうか
File transfer failed: host resolution failedホスト名とDNS設定
File transfer timed outネットワーク接続や操作時間
File transfer failed上記に分類できない接続・操作の失敗。renameの場合はPOSIX rename拡張への対応も確認してください。

例外を捕捉しなければ、エラーメッセージはCraftの実行ログに記録されます。複数の操作を組み合わせる場合は、それぞれの完了をログに記録すると、どこで失敗したかを確認できます。