transfer
MODULES.transferは、Craft Functionsから外部サーバーへファイルを転送するモジュールです。HTMLだけでなく、CSV・JSON・画像なども扱えます。
利用できる操作
Section titled “利用できる操作”| メソッド | 操作 | SCP | SFTP |
|---|---|---|---|
writeFile | 文字列またはBufferをファイルに書き込みます。 | 対応 | 対応 |
rename | ファイルを移動し、既存の移動先を原子的に置き換えます。 | 非対応 | POSIX rename拡張が必要 |
remove | ファイルを1つ削除します。 | 非対応 | 対応 |
各メソッドは独立して接続・切断します。接続を管理するためのconnectやcloseを呼び出す必要はありません。
各メソッドのconnectionに次のオブジェクトを渡します。
| プロパティ | 型 | 必須 | 説明 |
|---|---|---|---|
host | string | 必須 | 接続先のホスト名です。 |
port | number | 任意 | 接続先ポートです。省略時は22です。1〜65535の整数を指定します。 |
username | string | 必須 | 接続先のユーザー名です。 |
protocol | string | 必須 | 'scp'または'sftp'を指定します。自動的な切り替えは行いません。 |
password | string | 認証方式による | パスワード認証に使用します。 |
privateKey | string | 認証方式による | 秘密鍵の内容を指定します。鍵ファイルのパスは指定できません。 |
passphrase | string | 任意 | 暗号化された秘密鍵のパスフレーズです。privateKeyと併せて指定します。 |
hostKeySha256 | string | 任意 | 接続先のホスト鍵のSHA-256フィンガープリントです。 |
passwordとprivateKeyは、どちらか一方だけを指定してください。上記以外の接続オプションは指定できません。
hostKeySha256を指定すると、サーバーのホスト鍵が一致する場合だけ接続します。接続先管理者から信頼できる経路で取得した、SHA256:に続く43文字のBase64形式(末尾の=なし)を指定してください。
省略時はホスト鍵を検証しません。通信は暗号化されますが、接続先のなりすましは検知できません。省略する場合は、空文字やnullを渡さず、プロパティ自体を省略してください。
接続先の条件
Section titled “接続先の条件”- 公開IPv4アドレスへの接続に対応します。localhost、プライベートネットワーク、リンクローカル、その他の特殊用途・予約済みアドレスには接続できません。
- ホスト名の名前解決結果に接続を許可しないIPv4アドレスが含まれる場合も接続できません。
- IPv6には対応していません。
- リモートOSはPOSIXを対象としています。操作に必要な権限を持つアカウントと、作成済みの配置先ディレクトリを用意してください。
ファイルを書き込む例
Section titled “ファイルを書き込む例”あらかじめ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を取得することはありません。
writeFile
Section titled “writeFile”const result = await MODULES.transfer.writeFile({ connection, remotePath: '/uploads/export.csv', content: 'id,name\n1,example\n',});// result: { remotePath: '/uploads/export.csv', bytes: 18 }| パラメーター | 型 | 説明 |
|---|---|---|
connection | object | 接続設定です。SCPまたはSFTPを指定します。 |
remotePath | string | 接続先での配置先の絶対パスです。 |
content | string または 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は受け付けません。
rename
Section titled “rename”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拡張に対応し、同じファイルを操作できる必要があります。
remove
Section titled “remove”await MODULES.transfer.remove({ connection, remotePath: '/uploads/index.html.tmp',});connection.protocolには'sftp'を指定します。remotePathは削除するファイルの絶対パスです。完了時の戻り値はありません。
対象が存在しない場合も成功します。権限不足などのエラーでは失敗します。ディレクトリの再帰的な削除には対応していません。
- パスは最大4096文字の絶対パスで指定します。各ディレクトリ名・ファイル名は英数字または
_で始まり、英数字・_・-・.のみ使用できます。日本語・空白・..による親ディレクトリ指定は利用できません。 - ファイルの拡張子に制限はありません。親ディレクトリを自動作成する機能はありません。
- 各操作の名前解決・接続・転送などは合計30秒でタイムアウトします。Secretの取得時間は含みません。ファンクション全体のタイムアウトにも余裕を持たせてください。
- 通信が途切れた場合などは、エラーになってもサーバー側で操作が完了している可能性があります。自動リトライは行いません。
- ファイルの内容は変更しません。CMSの値をHTMLに埋め込む際のエスケープなどはユーザーコードで行ってください。
エラーの確認
Section titled “エラーの確認”入力値が不正な場合は、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の実行ログに記録されます。複数の操作を組み合わせる場合は、それぞれの完了をログに記録すると、どこで失敗したかを確認できます。