You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Python ftplib上传文件至FTP服务器时遇Connection refused错误

问题排查与解决方案

我仔细看了你的代码、错误回溯和FileZilla日志,发现两个关键问题,其中第二个是导致ConnectionRefusedError的核心原因:

1. 函数内部的变量引用错误

你的ftp_upload函数定义了参数ftp_obj,但函数内部却直接调用了全局的ftp变量,这是一个明显的bug。虽然在当前代码结构下可能暂时能运行,但这是不良编码习惯,后续复用函数时会引发问题。

修正方法:把函数内的ftp.storlinesftp.storbinary改成ftp_obj.storlinesftp_obj.storbinary

2. FTP主动模式被环境阻止(核心原因)

从FileZilla的日志可以看到,服务器返回了:

200 PORT command successful. Consider using PASV.

这说明服务器支持被动模式(PASV),并且推荐使用这种模式。而Python的ftplib.FTP默认使用主动模式(PORT),在这种模式下,当执行文件传输命令(比如STOR)时,FTP服务器需要主动发起连接到你的客户端端口,这个连接很可能被你的本地防火墙、路由器NAT规则或者服务器端的防火墙拦截,从而导致ConnectionRefusedError

解决方法:在登录FTP服务器后,调用ftp.set_pasv(True)切换到被动模式。


修正后的完整代码

import ftplib

def ftp_upload(ftp_obj, path, ftype='TXT'):
    """ 
    A function for uploading files to an FTP server
    @param ftp_obj: The file transfer protocol object
    @param path: The path to the file to upload
    """
    # 提取本地文件名,避免把本地路径当成远程路径
    filename = path.split('/')[-1]
    if ftype == 'TXT':
        with open(path) as fobj:
            # 修正:使用传入的ftp_obj而非全局ftp
            ftp_obj.storlines(f'STOR {filename}', fobj)
    else:
        with open(path, 'rb') as fobj:
            # 修正:使用传入的ftp_obj而非全局ftp
            ftp_obj.storbinary(f'STOR {filename}', fobj, 1024)

if __name__ == '__main__':
    ftp = ftplib.FTP(host='domain or i.p. address')
    ftp.login(user='username', passwd='password')
    # 新增:切换到被动模式,解决连接被拒绝问题
    ftp.set_pasv(True)
    
    path = input('Please provide path to file: ')
    ftp_upload(ftp, path)
    
    pdf_path = '/path/to/something.pdf'
    ftp_upload(ftp, pdf_path, ftype='PDF')
    
    ftp.quit()

额外优化说明:我还修改了STOR命令后的路径,只传入文件名(用path.split('/')[-1]提取),避免把本地的完整路径当成远程服务器上的路径,这样文件会直接上传到当前登录的目录下,和FileZilla的行为保持一致。


后续验证思路

如果修改后仍然有问题,可以尝试:

  • 确认服务器的被动模式端口范围(通常是1024-65535)是否在服务器端防火墙开放
  • 检查本地防火墙是否允许Python程序发起出站连接
  • 尝试升级Python版本(你的Python是3.6,虽然版本较老,但核心逻辑没问题,新版本可能有更完善的FTP兼容处理)

内容的提问来源于stack exchange,提问作者EliC

火山引擎 最新活动