Skip to content

Instantly share code, notes, and snippets.

@gh640
Created April 9, 2020 05:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gh640/cf2261d81095449f8d6c7dbc37916043 to your computer and use it in GitHub Desktop.
Save gh640/cf2261d81095449f8d6c7dbc37916043 to your computer and use it in GitHub Desktop.
サンプルコード: FTPS で特定のディレクトリ以下のファイルを一式ダウンロードするスクリプト
"""FTPS で production サーバーのファイルをダウンロードするスクリプトのサンプル"""
from contextlib import contextmanager
from ftplib import FTP_TLS
from pathlib import Path
REMOTE_ROOT = 'xxx'
LOCAL_ROOT = Path('xxx')
ENCODING = 'utf-8'
FTP_CONFIG = {'host': 'xxx', 'user': 'xxx', 'passwd': 'xxx'}
def main():
"""メイン関数"""
with ftps_connect() as ftp:
pull_files(ftp, REMOTE_ROOT, LOCAL_ROOT)
def pull_files(ftp: FTP_TLS, remote_dir: str, local_root: Path) -> None:
"""指定されたディレクトリ以下のファイル一式をダウンロードする"""
def get_full_path(path, filename):
return '{}/{}'.format(path, filename)
ftp.cwd(remote_dir)
# WFS ですべてのファイルを取得する
paths = ['.']
while paths:
path = paths.pop(0)
for filename, info in ftp.mlsd(path):
# カレントディレクトリ or ペアレントディレクトリ
if info['type'] in ('cdir', 'pdir'):
continue
# ディレクトリ
if info['type'] == 'dir':
paths.append(get_full_path(path, filename))
# ファイル
if info['type'] == 'file':
full_path = get_full_path(path, filename)
print(full_path)
local_path = local_root / full_path
local_path.parent.mkdir(parents=True, exist_ok=True)
with local_path.open('wb') as fp:
ftp.retrbinary('RETR {}'.format(full_path), fp.write)
@contextmanager
def ftps_connect():
"""文字エンコーディングセット済みの `FTP_TLS` インスタンスを返すコンテキストマネージャ"""
with FTP_TLS(**FTP_CONFIG) as ftp:
ftp.encoding = ENCODING
yield ftp
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment