サイトアイコン 知的好奇心

PythonでFTPアップロードを行う方法

PythonでFTPアップロードを行う方法をご紹介します。

条件

サンプルソース

以下がFTP接続して指定ファイルをアップロードするサンプルです。

import ftplib
from logging import getLogger, StreamHandler, Formatter, DEBUG


## ログ出力設定
logger = getLogger("FTP Test")
logger.setLevel(DEBUG)
stream_handler = StreamHandler()
stream_handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

## 接続先ホスト
HOST = 'XXX.com'
PORT = 21
USER = 'userName'
PASSWORD = 'password'
DIRECTORY = 'test'

## アップロードファイル名
FILE_NAME = 'test.jpg'


## FTP接続、ファイルアップロード
logger.debug('== Start FTP ==')
with FTP() as ftp:
    try:
        ftp.connect(HOST, PORT)   # ホスト、ポートを指定して接続
        ftp.login(USER, PASSWORD) # ユーザID、パスワードを指定してログイン
        ftp.cwd(DIRECTORY)        # 指定のディレクトリに移動
        with open(FILE_NAME, 'rb') as f:
            ftp.storbinary('STOR ' + FILE_NAME, f) # 対象ファイルをアップロード
    except ftplib.all_errors as e:
        logger.error('FTP error = %s' % e)
    else:
        logger.debug('FTP success.')
logger.debug('== End FTP ==')

処理の流れ

処理の流れは以下の通りです。

  1. 対象ホストに接続
  2. 対象ホストにログイン
  3. 指定のディレクトリに移動
  4. 対象ファイルをアップロード

解説

サーバー側の設定がおかしい場合の回避策

FTP接続を行うサーバー側の設定がおかしくて、「FTP接続は出来るけれどもデータが取得できない」という状況に出くわす場合があります。

詳細は以下の記事をご参照ください。

FTPで接続は出来るがデータ取得が出来ない場合の対応

回避策ソース

以下のような記述を追記します。

from ftplib import FTP


## ネットワーク設定問題の回避策
_old_makepasv = FTP.makepasv
def _new_makepasv(self):
    HOST, PORT = _old_makepasv(self)
    HOST = self.sock.getpeername()[0]
    return HOST, PORT
FTP.makepasv = _new_makepasv

回避策を含めた全体ソース

全体のソースは以下のようになります。

from ftplib import FTP
import ftplib
from logging import getLogger, StreamHandler, Formatter, DEBUG


## ログ出力設定
logger = getLogger("FTP Test")
logger.setLevel(DEBUG)
stream_handler = StreamHandler()
stream_handler.setLevel(DEBUG)
formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)

## 接続先ホスト
HOST = 'XXX.com'
PORT = 21
USER = 'userName'
PASSWORD = 'password'
DIRECTORY = 'test'

## アップロードファイル名
FILE_NAME = 'test.jpg'


## ネットワーク設定がおかしい場合の回避策
_old_makepasv = FTP.makepasv
def _new_makepasv(self):
    HOST, PORT = _old_makepasv(self)
    HOST = self.sock.getpeername()[0]
    return HOST, PORT
FTP.makepasv = _new_makepasv


## FTP接続、ファイルアップロード
logger.debug('== Start FTP ==')
with FTP() as ftp:
    try:
        ftp.connect(HOST, PORT)   # ホスト、ポートを指定して接続
        ftp.login(USER, PASSWORD) # ユーザID、パスワードを指定してログイン
        ftp.cwd(DIRECTORY)        # 指定のディレクトリに移動
        with open(FILE_NAME, 'rb') as f:
            ftp.storbinary('STOR ' + FILE_NAME, f) # 対象ファイルをアップロード
    except ftplib.all_errors as e:
        logger.error('FTP error = %s' % e)
    else:
        logger.debug('FTP success.')
logger.debug('== End FTP ==')

参考

Python:ftplib — FTPプロトコルクライアント

https://docs.python.org/ja/3/library/ftplib.html

モバイルバージョンを終了