もう迷わない!Python ftplib.FTP.storbinary()のエラーと解決策

2025-06-06

ftplib.FTP.storbinary() とは?

storbinary()メソッドは、ローカルのファイルを読み込み、その内容をFTPサーバーにバイナリデータとして送信します。これは、画像、動画、実行ファイルなどの、テキストとして解釈できないファイルを転送する際に使用されます。

基本的な書式

FTP.storbinary(cmd, fp, blocksize=8192, callback=None, rest=None)
  • rest (オプション, デフォルト: None):

    • ファイル転送を途中から再開する場合に、転送を開始するバイトオフセットを指定します。
  • callback (オプション, デフォルト: None):

    • データブロックが送信されるたびに呼び出される、単一の引数を取る関数を指定できます。
    • このコールバック関数には、送信されたデータブロック(bytes型)が引数として渡されます。
    • 進捗バーの表示など、転送状況を監視したい場合に便利です。
  • blocksize (オプション, デフォルト: 8192):

    • 一度にファイルから読み込み、FTPサーバーに送信するデータのバイト数を指定します。
    • この値を調整することで、転送パフォーマンスに影響を与えることがあります。
  • fp (file-like object):

    • アップロードするローカルのファイルオブジェクトを指定します。
    • このファイルオブジェクトは、バイナリモード ('rb') で開かれている必要があります。
    • read(num_bytes) メソッドを持つ必要があります。storbinary()はこのメソッドを使ってファイルからデータを読み込みます。
  • cmd:

    • FTPサーバーに送信するコマンド文字列を指定します。通常は、"STOR filename" の形式で、filename はFTPサーバー上に作成されるファイル名です。
    • 例: "STOR my_image.jpg"
    • 注意点として、storbinary()メソッド自体がFTPサーバーのカレントディレクトリにファイルをアップロードするため、アップロード先のパスを制御したい場合は、事前にftp.cwd('/path/to/directory')のようにしてカレントディレクトリを移動しておく必要があります。

使用例

from ftplib import FTP

# FTPサーバーへの接続情報
FTP_HOST = 'your_ftp_host.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'

# アップロードするローカルファイル
LOCAL_FILE_PATH = 'local_image.jpg'
# FTPサーバー上でのファイル名
REMOTE_FILE_NAME = 'uploaded_image.jpg'

try:
    with FTP(FTP_HOST) as ftp:
        # ログイン
        ftp.login(user=FTP_USER, passwd=FTP_PASS)
        print(f"FTPサーバーに接続しました: {FTP_HOST}")

        # FTPサーバーのカレントディレクトリを移動する(必要であれば)
        # ftp.cwd('/path/to/remote/directory') 

        # アップロードするファイルをバイナリモードで開く
        with open(LOCAL_FILE_PATH, 'rb') as fp:
            # storbinary() を使ってファイルをアップロード
            # コールバック関数で進捗を表示する例
            bytes_sent = 0
            total_size = len(fp.read()) # ファイルサイズを取得
            fp.seek(0) # ファイルポインタを先頭に戻す

            def handle_progress(block):
                nonlocal bytes_sent
                bytes_sent += len(block)
                percentage = (bytes_sent / total_size) * 100
                print(f"\r進捗: {percentage:.2f}% ({bytes_sent}/{total_size} bytes)", end="")

            ftp.storbinary(f'STOR {REMOTE_FILE_NAME}', fp, callback=handle_progress)
            print("\nファイルアップロードが完了しました!")

except Exception as e:
    print(f"エラーが発生しました: {e}")

finally:
    # withステートメントを使用しているため、ftp.quit()やfp.close()は自動的に行われます
    pass
  • エラーハンドリング: FTP通信はネットワークに依存するため、エラーが発生する可能性があります。try-exceptブロックを使用して適切にエラーハンドリングを行うことが重要です。
  • ディレクトリの指定: storbinary()cmd引数に指定するファイル名には、通常、パスを含めません。FTPサーバー上の特定のディレクトリにアップロードしたい場合は、事前にftp.cwd()メソッドでカレントディレクトリを移動しておく必要があります。
  • バイナリモードでのファイルオープン: アップロードするローカルファイルは必ずバイナリモード ('rb') で開いてください。テキストモード ('r') で開くと、予期せぬ文字コード変換などによりファイルが破損する可能性があります。


ログインまたは接続の問題 (Authentication/Connection Issues)

エラーメッセージ例

  • ftplib.error_perm: 530 Not logged in. (ログインしていない)
  • ftplib.all_errors: 530 Login incorrect. (ログイン情報間違い)
  • ftplib.all_errors: [Errno 111] Connection refused (接続拒否)
  • ftplib.all_errors: [Errno 11001] getaddrinfo failed (ホスト名解決失敗)

原因

  • ファイアウォールによるブロック
    クライアント側またはサーバー側のファイアウォールが接続をブロックしている。
  • FTPサーバーが起動していない/応答していない
    サーバー側で問題が発生している。
  • ユーザー名/パスワードの誤り
    認証情報が間違っている。
  • ポート番号の誤り
    デフォルトの21番ポート以外を使用している。
  • FTPホスト名/IPアドレスの誤り
    サーバーアドレスが間違っている。

トラブルシューティング

  • FTPサーバーの状態確認
    FTPサーバーの管理者であれば、サーバーが正常に稼働しているか確認します。
  • ファイアウォールの確認
    クライアントPCのファイアウォール設定、またはサーバー側のファイアウォール設定を確認し、FTPポート(通常21番)が許可されているか確認します。
  • FTPクライアントでのテスト
    FileZillaなどのGUIベースのFTPクライアントを使って、同じ接続情報でFTPサーバーに接続できるか試します。これができれば、Pythonコードの問題である可能性が高いです。
  • pingテスト
    コマンドプロンプトやターミナルで ping your_ftp_host.com を実行し、サーバーへの基本的な接続性を確認します。
  • 接続情報の確認
    ホスト名、ポート、ユーザー名、パスワードが正しいことを再確認します。

ファイルパスまたは権限の問題 (File Path/Permission Issues)

エラーメッセージ例

  • ftplib.error_perm: 553 Could not create file. (ファイル作成失敗)
  • ftplib.error_perm: 550 Permission denied. (権限不足)
  • ftplib.error_perm: 550 CWD failed. "/nonexistent_dir": No such file or directory. (ディレクトリが見つからない)

原因

  • ディスク容量不足
    FTPサーバーのディスク容量が不足している。
  • ファイル名が無効
    FTPサーバーで許可されていない文字が含まれるファイル名を指定している。
  • 書き込み権限の不足
    ログインしたFTPユーザーが、指定したディレクトリにファイルを書き込む権限を持っていない。
  • リモートディレクトリの誤り
    ftp.cwd()で指定したディレクトリが存在しないか、スペルミスがある。

トラブルシューティング

  • ディスク容量の確認
    FTPサーバーのディスク容量に余裕があるか確認します。
  • ファイル名の確認
    アップロードするファイル名が、FTPサーバーのファイル名規則に違反していないか確認します。
  • 権限の確認
    FTPサーバーの管理者であれば、FTPユーザーに該当ディレクトリへの書き込み権限が付与されているか確認します。
  • リモートパスの確認
    ftp.pwd() で現在の作業ディレクトリを確認し、ftp.nlst() でディレクトリ内のファイル一覧を確認して、目的のディレクトリが存在するか確認します。

バイナリモードの誤り (Incorrect Binary Mode)

エラーメッセージ例

  • ファイルがアップロードされるが、開くと破損している
  • TypeError: a bytes-like object is required, not 'str' (storbinaryに文字列を渡した)

原因

  • ローカルファイルをテキストモードで開いている
    open(LOCAL_FILE_PATH, 'r') のように 'r' でファイルを開いてしまい、storbinary()に渡している。storbinary()はバイナリデータを期待しているため、この場合エラーになるか、ファイルが破損します。

トラブルシューティング

  • ファイルをバイナリモードで開く
    必ず open(LOCAL_FILE_PATH, 'rb') のように 'rb' (read binary) でファイルを開くようにします。

パッシブモード/アクティブモードの問題 (Passive/Active Mode Issues)

エラーメッセージ例

  • EOF occurred in violation of protocol (プロトコル違反)
  • アップロードが途中で止まる、または非常に遅い。
  • ftplib.all_errors: [Errno 10054] Connection reset by peer (接続がリセットされた)

原因

  • ファイアウォールやNATによるデータ接続のブロック
    FTPはデータ転送に別途データコネクションを確立します。
    • アクティブモード
      クライアントがサーバーにデータポートを開くように指示し、サーバーがそのポートに接続します。クライアント側のファイアウォールがこの着信接続をブロックすることがよくあります。
    • パッシブモード (デフォルト)
      クライアントがサーバーにデータポートを開くように要求し、サーバーはそのポート番号をクライアントに通知します。クライアントがそのポートに接続します。サーバー側のファイアウォールがパッシブポート範囲をブロックしていることがあります。

トラブルシューティング

  • ネットワーク管理者に相談
    企業ネットワークなど、厳格なファイアウォールがある環境では、ネットワーク管理者に相談してFTPのデータポート範囲を許可してもらう必要がある場合があります。
  • FTPサーバーのログの確認
    サーバー側のFTPログを確認すると、データコネクションの確立に関するエラーや、ファイアウォールによって接続が拒否されたなどの情報が得られる場合があります。
  • アクティブモードの試行 (非推奨だが有効な場合あり)
    ftp.set_pasv(False) を呼び出してアクティブモードを試してみます。ただし、クライアント側のファイアウォールでFTPのアクティブモードを許可する必要があるため、通常はあまり推奨されません。
  • パッシブモードの明示的な設定 (推奨)
    ほとんどの場合、パッシブモードの方がファイアウォールフレンドリーです。ftp.set_pasv(True) を呼び出してパッシブモードを明示的に有効にしてみます(ftplibのデフォルトはTrueですが、念のため)。

タイムアウト (Timeout)

エラーメッセージ例

  • socket.timeout: timed out

原因

  • 大きなファイルの転送
    非常に大きなファイルを転送している場合、デフォルトのタイムアウトでは足りないことがあります。
  • サーバーが応答しない
    サーバーがビジーであるか、何らかの問題で応答が遅い。
  • ネットワークが不安定
    ネットワークの速度が遅い、またはパケットロスが多い。
  • ファイルを分割してアップロード
    非常に大きなファイルの場合、ファイルを小さなチャンクに分割してアップロードすることを検討します。
  • ネットワーク環境の確認
    自身のネットワーク接続に問題がないか確認します。
  • タイムアウト値の延長
    FTPオブジェクトを作成する際に、timeout引数を指定してタイムアウト値を長く設定します。
    from ftplib import FTP
    ftp = FTP(FTP_HOST, timeout=60) # 60秒に設定
    
  • ftplib.error_perm: 500 Unknown command.: storbinarycmd引数に"STOR filename"以外の不適切なコマンドを渡している場合に発生することがあります。
  • 公式ドキュメントの参照
    ftplibの公式ドキュメントには、詳細な情報や例外クラスについて記載されています。
  • withステートメントの使用
    ファイルオブジェクトやFTP接続は、withステートメントを使用して開くことを強く推奨します。これにより、エラーが発生した場合でも確実にリソースが閉じられ、リソースリークを防ぐことができます。
  • 簡略化されたテストコードの作成
    問題が発生している特定のstorbinary()の部分だけを抜き出して、最小限のコードで問題を再現できるか試します。これにより、問題の範囲を絞り込むことができます。
  • FTPサーバーのログを確認
    FTPサーバー側でエラーログが出力されていないか確認します。クライアント側ではわからないサーバー側の問題が明らかになることがあります。
  • デバッグ出力の追加
    コードに print() ステートメントを追加して、現在のディレクトリ、ファイルパス、ログイン状態などを確認します。
  • エラーメッセージをよく読む
    Pythonが返すエラーメッセージは、問題の特定に役立つ多くの情報を含んでいます。特に ftplib.all_errorsftplib.error_perm などの例外クラスと、それに続くFTPサーバーからの応答コード(例: 550, 530)に注目します。


例1:基本的なファイルのアップロード

最も一般的な使用例です。ローカルにあるファイルを指定したファイル名でFTPサーバーにアップロードします。

from ftplib import FTP
import os

# FTPサーバーへの接続情報
FTP_HOST = 'your_ftp_host.com'    # FTPサーバーのホスト名またはIPアドレス
FTP_USER = 'your_username'        # FTPユーザー名
FTP_PASS = 'your_password'        # FTPパスワード

# アップロードするローカルファイルの情報
LOCAL_FILE_NAME = 'my_document.pdf' # ローカルにあるファイル名(例: カレントディレクトリに存在する場合)
REMOTE_FILE_NAME = 'uploaded_document.pdf' # FTPサーバー上に作成されるファイル名

try:
    # FTPオブジェクトを作成し、withステートメントで接続を管理する
    # withを使うことで、処理終了時に自動的に接続が閉じられる
    with FTP(FTP_HOST) as ftp:
        # ログイン
        ftp.login(user=FTP_USER, passwd=FTP_PASS)
        print(f"FTPサーバーに接続しました: {FTP_HOST}")
        print(f"現在のディレクトリ: {ftp.pwd()}") # 現在のFTPサーバー上のディレクトリを確認

        # アップロード先のディレクトリが存在しない場合、作成することもできる
        # REMOTE_DIR = '/path/to/remote/directory'
        # if REMOTE_DIR not in ftp.nlst(): # nlst()でディレクトリ一覧を取得
        #     ftp.mkd(REMOTE_DIR) # ディレクトリを作成
        # ftp.cwd(REMOTE_DIR) # アップロード先のディレクトリに移動

        # アップロードするファイルをバイナリ読み込みモードで開く
        # 'rb' は "read binary" の意味
        with open(LOCAL_FILE_NAME, 'rb') as fp:
            # storbinary() を使ってファイルをアップロード
            # 第一引数: FTPサーバーに送信するコマンド (例: "STOR <ファイル名>")
            # 第二引数: 読み込みモードで開かれたファイルオブジェクト
            ftp.storbinary(f'STOR {REMOTE_FILE_NAME}', fp)
            print(f"'{LOCAL_FILE_NAME}' を '{REMOTE_FILE_NAME}' としてアップロードしました。")

        # アップロード後のファイル一覧を確認(オプション)
        print("\nFTPサーバー上のファイル一覧:")
        ftp.dir() # ファイルとディレクトリの詳細リストを表示

except Exception as e:
    print(f"エラーが発生しました: {e}")

finally:
    # withステートメントを使用しているため、明示的なftp.quit()やfp.close()は不要
    pass

解説

  1. from ftplib import FTP: ftplib モジュールから FTP クラスをインポートします。
  2. 接続情報の定義: FTP_HOST, FTP_USER, FTP_PASS に各自のFTPサーバー情報を設定します。
  3. with FTP(FTP_HOST) as ftp
    : FTP オブジェクトを作成し、with ステートメントでコンテキストマネージャーとして使用します。これにより、処理の最後に自動的にFTP接続が閉じられます。
  4. ftp.login(user=FTP_USER, passwd=FTP_PASS): FTPサーバーにログインします。
  5. open(LOCAL_FILE_NAME, 'rb') as fp
    : アップロードするローカルファイルをバイナリ読み込みモード ('rb') で開きます。ここが非常に重要です。バイナリファイルは必ず 'rb' で開いてください。
  6. ftp.storbinary(f'STOR {REMOTE_FILE_NAME}', fp): storbinary メソッドを呼び出してファイルをアップロードします。
    • 'STOR {REMOTE_FILE_NAME}': FTPサーバーに「このファイル名で保存する」という命令を送信します。
    • fp: 開かれたファイルオブジェクトを渡します。storbinary はこのオブジェクトからデータを読み取って送信します。

例2:アップロードの進捗状況を表示する (Callback関数を使用)

大きなファイルをアップロードする際に、進捗状況をユーザーに表示したい場合があります。storbinary() メソッドの callback 引数を利用します。

from ftplib import FTP
import os
import sys

# FTPサーバーへの接続情報
FTP_HOST = 'your_ftp_host.com'
FTP_USER = 'your_username'
FTP_PASS = 'your_password'

# アップロードするローカルファイルの情報
LOCAL_FILE_NAME = 'large_image.zip' # 大容量ファイル
REMOTE_FILE_NAME = 'uploaded_large_image.zip'

# 進捗状況を表示するコールバック関数
# この関数は、storbinaryがブロックを送信するたびに呼び出されます
def handle_progress(block):
    global bytes_sent
    bytes_sent += len(block)
    # 進捗パーセンテージを計算して表示
    percentage = (bytes_sent / total_size) * 100
    sys.stdout.write(f"\r進捗: {percentage:.2f}% ({bytes_sent}/{total_size} bytes)")
    sys.stdout.flush() # 出力を即座に表示

bytes_sent = 0
total_size = 0 # ファイルの総サイズを格納する変数

try:
    with FTP(FTP_HOST) as ftp:
        ftp.login(user=FTP_USER, passwd=FTP_PASS)
        print(f"FTPサーバーに接続しました: {FTP_HOST}")

        # アップロードするファイルの総サイズを取得
        # ファイルポインタを動かすため、後でseek(0)で戻す必要があります
        with open(LOCAL_FILE_NAME, 'rb') as fp_size:
            total_size = os.fstat(fp_size.fileno()).st_size
        
        print(f"'{LOCAL_FILE_NAME}' ({total_size} bytes) をアップロード中...")

        with open(LOCAL_FILE_NAME, 'rb') as fp_upload:
            # storbinaryのcallback引数にhandle_progress関数を指定
            ftp.storbinary(f'STOR {REMOTE_FILE_NAME}', fp_upload, callback=handle_progress)
            print("\nファイルアップロードが完了しました!")

except Exception as e:
    print(f"\nエラーが発生しました: {e}")

解説

  1. handle_progress(block) 関数:
    • block 引数には、storbinary が一度に送信したバイナリデータのチャンク(bytes オブジェクト)が渡されます。
    • len(block) でそのチャンクのサイズを取得し、グローバル変数 bytes_sent に加算します。
    • sys.stdout.write()\r を使うことで、同じ行に進捗状況を上書き表示し、見やすい進捗バーのように見せます。
  2. total_size の取得: os.fstat(fp_size.fileno()).st_size を使って、ファイル全体のサイズを事前に取得しています。これにより、進捗パーセンテージを正確に計算できます。
  3. callback=handle_progress: storbinary メソッドの callback 引数に handle_progress 関数を渡すことで、データブロックが送信されるたびにこの関数が呼び出されるようになります。

FTP通信を暗号化したい場合は、ftplib.FTP_TLS クラスを使用します。これはSSL/TLSをサポートするFTPのサブクラスです。

from ftplib import FTP_TLS
import os
import ssl # SSL/TLSコンテキストをカスタマイズする場合に必要

# FTPSサーバーへの接続情報
FTPS_HOST = 'your_ftps_host.com'
FTPS_USER = 'your_username'
FTPS_PASS = 'your_password'
# FTPSのポートは通常21 (コントロール接続) または990 (Implicit TLS) ですが、
# 明示的TLS (Explicit TLS) の場合は21番ポートが使われることが多いです。
# サーバー設定に依存します。
FTPS_PORT = 21 

LOCAL_FILE_NAME = 'secure_document.zip'
REMOTE_FILE_NAME = 'uploaded_secure_document.zip'

try:
    # FTP_TLS オブジェクトを作成し、withステートメントで接続を管理
    with FTP_TLS(FTPS_HOST, FTPS_PORT) as ftps:
        # TLSハンドシェイクを開始 (コントロール接続を暗号化)
        # サーバー証明書の検証を行う場合は、validate_certs=True を指定
        # 必要に応じて、ssl.create_default_context() でコンテキストをカスタマイズ
        ftps.set_debuglevel(2) # デバッグレベルを設定すると、SSLハンドシェイクの詳細が表示される
        ftps.auth() # Explicit FTPSの場合、認証コマンドを送信
        ftps.prot_p() # データチャネルも保護 (Private) に設定 (Implicit FTPSの場合は不要)

        ftps.login(user=FTPS_USER, passwd=FTPS_PASS)
        print(f"FTPSサーバーに接続しました: {FTPS_HOST}")
        print(f"現在のディレクトリ: {ftps.pwd()}")

        with open(LOCAL_FILE_NAME, 'rb') as fp:
            ftps.storbinary(f'STOR {REMOTE_FILE_NAME}', fp)
            print(f"'{LOCAL_FILE_NAME}' を '{REMOTE_FILE_NAME}' としてセキュアにアップロードしました。")

except Exception as e:
    print(f"エラーが発生しました: {e}")

解説

  1. from ftplib import FTP_TLS: FTP_TLS クラスをインポートします。
  2. with FTP_TLS(FTPS_HOST, FTPS_PORT) as ftps
    : FTP_TLS オブジェクトを作成します。
  3. ftps.auth(): サーバーに対してTLS認証を開始するよう要求します(Explicit FTPSの場合)。
  4. ftps.prot_p(): データ転送(ファイルアップロードなど)も暗号化されるように設定します。これを呼び出さないと、コントロール接続は暗号化されてもデータ転送は平文のままになる可能性があります(サーバー設定による)。
  5. 以降のファイルオープンと storbinary の使い方は FTP クラスと同じです。

上記の例では、try...except Exception as e: を使用して一般的なエラーを捕捉していますが、より堅牢なプログラムを作成するためには、ftplib が提供する具体的な例外(ftplib.all_errorsftplib.error_perm など)を捕捉し、それぞれのエラータイプに応じた処理を行うことが推奨されます。



ftplib.FTP.storlines() (テキストモードでのアップロード)

storbinary()がバイナリモードでファイルをアップロードするのに対し、storlines()はテキストモードでファイルをアップロードします。主にテキストファイル(例:.txt, .log, .csvなど)を転送する際に使用され、行末コードの変換などが行われます。

特徴

  • バイナリファイルには不向き: 画像や実行ファイルなどのバイナリファイルをこれで転送すると、ファイルが破損する可能性があります。
  • テキストファイルの転送に特化: 行ごとに処理され、必要に応じて改行コード(CRLF, LFなど)が自動的に変換されます。

書式

FTP.storlines(cmd, fp, callback=None)

使用例

from ftplib import FTP

# ... 接続情報とファイル情報を定義 ...

LOCAL_TEXT_FILE = 'my_text_file.txt'
REMOTE_TEXT_FILE = 'uploaded_text_file.txt'

try:
    with FTP(FTP_HOST) as ftp:
        ftp.login(user=FTP_USER, passwd=FTP_PASS)
        print("FTPサーバーに接続しました (storlinesを使用)")

        with open(LOCAL_TEXT_FILE, 'r') as fp: # 'r' (read text) モードで開く
            ftp.storlines(f'STOR {REMOTE_TEXT_FILE}', fp)
            print(f"'{LOCAL_TEXT_FILE}' を '{REMOTE_TEXT_FILE}' としてアップロードしました (storlines)。")

except Exception as e:
    print(f"エラーが発生しました: {e}")

paramiko ライブラリ (SFTP)

FTPはデータが暗号化されないため、セキュリティ上の懸念があります。よりセキュアなファイル転送が必要な場合、SFTP(SSH File Transfer Protocol)が推奨されます。paramikoはPythonでSSH2プロトコルを実装するためのライブラリで、SFTPクライアント機能も提供します。

特徴

  • 依存関係: paramikoライブラリをインストールする必要があります(pip install paramiko)。
  • パスワード認証、鍵認証: パスワードだけでなく、SSHキーペア(秘密鍵と公開鍵)による認証もサポートします。
  • セキュアな転送: 全てのデータがSSHトンネル経由で暗号化されて転送されます。

使用例

import paramiko
import os

# SFTPサーバーへの接続情報
SFTP_HOST = 'your_sftp_host.com'
SFTP_PORT = 22 # 通常のSSHポート
SFTP_USER = 'your_username'
SFTP_PASS = 'your_password' # または private_key_path = '/path/to/your/key.pem'

LOCAL_FILE_PATH = 'my_secret_data.txt'
REMOTE_FILE_PATH = '/remote/path/to/uploaded_secret_data.txt'

try:
    with paramiko.SSHClient() as client:
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # 初回接続時にホストキーを自動追加
        
        # パスワード認証の場合
        client.connect(SFTP_HOST, port=SFTP_PORT, username=SFTP_USER, password=SFTP_PASS)
        
        # 鍵認証の場合 (パスワードの代わりに鍵ファイルを指定)
        # client.connect(SFTP_HOST, port=SFTP_PORT, username=SFTP_USER, key_filename=private_key_path)

        with client.open_sftp() as sftp:
            sftp.put(LOCAL_FILE_PATH, REMOTE_FILE_PATH)
            print(f"'{LOCAL_FILE_PATH}' を '{REMOTE_FILE_PATH}' としてSFTPでアップロードしました。")

except paramiko.AuthenticationException:
    print("SFTP認証に失敗しました。ユーザー名/パスワードまたは鍵ファイルを確認してください。")
except paramiko.SSHException as e:
    print(f"SFTP接続またはSSHエラー: {e}")
except Exception as e:
    print(f"その他のエラー: {e}")

requests ライブラリ (HTTP/HTTPS経由のアップロード)

FTPサーバーではなく、HTTP/HTTPSプロトコルを介してファイルをアップロードできるWebサービスやAPIを利用する場合、requestsライブラリが非常に強力です。これはFTPとは根本的に異なるプロトコルですが、WebベースのファイルアップロードフォームやRESTful APIを介してファイルを送信する一般的な方法です。

特徴

  • 依存関係: requestsライブラリをインストールする必要があります(pip install requests)。
  • 豊富な機能: GET/POSTリクエスト、ヘッダー操作、セッション管理、認証など、HTTP通信のあらゆる側面をサポートします。
  • Webベースのアップロード: Webサーバーやクラウドストレージサービスへのアップロードに適しています。

使用例
これはFTPとは直接関連しませんが、Webサービスへのアップロードの一般的な例です。

import requests

# アップロード先のURL(例: WebフォームのPOSTエンドポイント、APIのエンドポイントなど)
UPLOAD_URL = 'http://your-web-service.com/upload' # または https://...

# アップロードするローカルファイル
LOCAL_FILE_PATH = 'upload_to_web.jpg'

try:
    with open(LOCAL_FILE_PATH, 'rb') as f:
        # files辞書にファイルオブジェクトを指定すると、multipart/form-dataとして送信される
        files = {'file': (os.path.basename(LOCAL_FILE_PATH), f, 'image/jpeg')} # 'image/jpeg' はMIMEタイプ
        # 必要に応じて、認証情報などをheadersやauth引数で追加
        # headers = {'Authorization': 'Bearer YOUR_TOKEN'}

        response = requests.post(UPLOAD_URL, files=files)

        if response.status_code == 200:
            print(f"'{LOCAL_FILE_PATH}' をWebサービスにアップロードしました。")
            print(f"サーバーからの応答: {response.text}")
        else:
            print(f"アップロードに失敗しました。ステータスコード: {response.status_code}")
            print(f"エラーメッセージ: {response.text}")

except requests.exceptions.RequestException as e:
    print(f"リクエストエラー: {e}")
except Exception as e:
    print(f"その他のエラー: {e}")

ファイルをクラウドストレージサービス(Amazon S3, Google Cloud Storage, Azure Blob Storageなど)にアップロードする場合、各サービスが提供するPython SDK(Software Development Kit)を使用するのが最も一般的で効率的な方法です。

特徴

  • 依存関係: 各サービスのSDKをインストールする必要があります(例: pip install boto3 for AWS S3)。
  • 認証とセキュリティ: 各サービスの認証メカニズム(IAMロール、APIキーなど)を直接利用できます。
  • スケーラビリティと信頼性: クラウドサービスが提供する高可用性と耐久性を享受できます。
  • 各サービスに最適化: 各クラウドストレージの特性やAPIに最適化されています。

使用例 (AWS S3の場合)

import boto3
import os

# AWS S3 接続情報
AWS_ACCESS_KEY_ID = 'YOUR_AWS_ACCESS_KEY_ID'
AWS_SECRET_ACCESS_KEY = 'YOUR_AWS_SECRET_ACCESS_KEY'
AWS_REGION = 'ap-northeast-1' # 例: 東京リージョン
S3_BUCKET_NAME = 'your-s3-bucket-name'

LOCAL_FILE_PATH = 'data_backup.zip'
S3_OBJECT_KEY = 'backups/data_backup_20250605.zip' # S3バケット内のパスとファイル名

try:
    s3 = boto3.client(
        's3',
        aws_access_key_id=AWS_ACCESS_KEY_ID,
        aws_secret_access_key=AWS_SECRET_ACCESS_KEY,
        region_name=AWS_REGION
    )

    s3.upload_file(LOCAL_FILE_PATH, S3_BUCKET_NAME, S3_OBJECT_KEY)
    print(f"'{LOCAL_FILE_PATH}' をS3バケット '{S3_BUCKET_NAME}' の '{S3_OBJECT_KEY}' にアップロードしました。")

except Exception as e:
    print(f"S3アップロードエラー: {e}")

ftplib.FTP.storbinary() は、Python標準ライブラリでFTPを介してバイナリファイルをアップロードする際の基本的な方法です。しかし、セキュリティ要件、対象のサーバーの種類(FTP, SFTP, HTTP/Webサービス, クラウドストレージ)、または機能の要件(進捗表示、エラーハンドリングの容易さなど)に応じて、上記のような代替方法を検討することが重要です。

  • テキストファイルのみのFTP: ftplib.FTP.storlines() も選択肢。
  • クラウドストレージへのアップロード: 各クラウドプロバイダのSDKを検討。
  • Webサービスへのアップロード: requests (HTTP/HTTPS) を検討。
  • セキュアなFTPが必要: paramiko (SFTP) を検討。