You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python ftplib实现FTPS传输失败,WinSCP却可正常运行

FTPS文件传输426错误问题排查与解决建议

问题概述

使用Python的ftplib实现FTPS文件传输时,第一个文件已在服务器生成且内容正确,但最终抛出ftplib.error_temp: 426 Transfer failed异常,无法完成传输。WinSCP可正常连接并传输文件,寻求可行的Python解决方案。

代码片段

# 注:代码存在导入缺失、方法调用错误及未定义变量问题
import pysftp
from io import BytesIO  # 补充缺失的导入
from ftplib import FTP_TLS  # 补充缺失的导入

user = "..."
password = "..."
host = "..."
port = 21
targetdir = "ftp_test_a"  # 补充缺失的目标目录定义

class FtpDirectory:
    def __init__(self):
        self.ftp = None

    def __enter__(self):
        self.ftp = FTP_TLS()
        self.ftp.debugging = 1
        self.ftp.connect(host, port)
        self.ftp.login(user, password)
        # ftplib.FTP_TLS无prot_p()方法,替换为发送PROT命令
        self.ftp.sendcmd('PROT P')

        self.ftp.cwd(targetdir)
        return self.ftp

files = [('test1.txt', b'test1content'), ('test2.txt', b'test2content')]

with FtpDirectory() as ftp:
    for file in files:
        ftp.storbinary("STOR " + file[0], BytesIO(file[1]))

错误日志

*resp* '220 myexampleserver.xyz X2 WS_FTP Server 8.7.2(01051325)'
*cmd* 'AUTH TLS'
*resp* '234 SSL enabled and waiting for negotiation'      
*cmd* 'USER myexampleuser'
*resp* '331 Enter password'   
*cmd* 'PASS ************'
*resp* '230 User logged in'
*cmd* 'PBSZ 0'
*resp* '200 PBSZ=0'
*cmd* 'PROT P'     
*resp* '200 PRIVATE data channel protection level set'
*cmd* 'CWD ftp_test_a'
*resp* '250 Command CWD succeed'
*cmd* 'TYPE I'
*resp* '200 Transfer mode set to BINARY'
*cmd* 'PASV'
*resp* '227 Entering Passive Mode (111,222,33,44,156,110).'
*cmd* 'STOR test.txt'
*resp* '150 Uploading in BINARY file test1.txt' <---- 耗时较久,文件已出现在服务器
*cmd* 'QUIT'
*resp* '426 Transfer failed' 

WinSCP配置对比

  • 加密方式:要求显式TLS/SSL(对应代码中AUTH TLS流程)
  • 传输模式:被动模式(与代码中PASV命令一致)
  • 数据通道保护:私有模式(对应PROT P命令)

环境信息

Python环境支持TLS 1.3(通过urlopen('https://www.howsmyssl.com/a/check', context=ssl._create_unverified_context()).read()验证)

解决建议

1. 修正现有代码错误

  • 补充缺失的导入语句:from ftplib import FTP_TLS和from io import BytesIO
  • 替换无效的prot_p()方法调用:使用self.ftp.sendcmd('PROT P')发送数据通道保护命令
  • 定义targetdir变量,明确目标目录路径

2. 处理数据通道TLS会话复用问题

WS_FTP Server 8.7.2可能要求数据通道复用控制通道的TLS会话,而ftplib默认未处理该逻辑。可尝试在每次传输前重新初始化数据通道:

with FtpDirectory() as ftp:
    for file in files:
        # 重新设置数据通道加密
        ftp.sendcmd('PROT P')
        ftp.storbinary("STOR " + file[0], BytesIO(file[1]))

3. 使用pysftp替代ftplib

pysftp基于paramiko,对FTPS的兼容性更完善,示例代码:

import pysftp
from io import BytesIO

user = "..."
password = "..."
host = "..."
port = 21
targetdir = "ftp_test_a"

files = [('test1.txt', b'test1content'), ('test2.txt', b'test2content')]

# 若服务器证书未被信任,添加cnopts=pysftp.CnOpts(hostkeys=None)(仅测试环境使用)
with pysftp.Connection(host, username=user, password=password, port=port) as sftp:
    sftp.cwd(targetdir)
    for file_name, content in files:
        with sftp.open(file_name, 'wb') as f:
            f.write(content)

4. 检查服务器端日志

查看WS_FTP Server的详细日志,确认426错误的具体触发原因(如数据连接超时、TLS握手失败、权限限制等),针对性调整配置。

内容的提问来源于stack exchange,提问作者A. L

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:10:34