Reputation: 43
I'm trying to use ftps to send a file to a FTP server. Login and changing directory work:
import ftplib
ftps = ftplib.FTP_TLS('host','user','pwd')
ftps.set_pasv(True)
ftps.prot_p()
ftps.cwd('/target_directory')
however when I try to upload my file:
file = open(file, 'rb')
send_cmd = 'STOR file_name.txt'
ftps.storbinary(send_cmd, file)
file.close()
ftps.quit()
I get the following error:
File "/script/location/script.py", line 161, in <module>
ftps.storbinary(send_cmd,file)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 772, in storbinary
return self.voidresp()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 229, in voidresp
resp = self.getresp()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ftplib.py", line 222, in getresp
raise error_temp, resp
ftplib.error_temp: 425 Unable to build data connection: Operation not permitted
I've read that the 425 response code is often a result of being in active mode, which is why I included ftps.set_pasv(True)
(although this is True by default).
I've also tried just listing the directory contents using ftps.retrlines('LIST')
but get essentially the same error. I'm using Python 2.7.10. Any help would be greatly appreciated.
Upvotes: 3
Views: 4041
Reputation: 3
thanks @pin3da, finaly I fix the bug, it takes a while to find your answer. But for me, it needs to modify a little bit, like below, hope it could help someone else who are struggling on this problem (a decade ago problem) like me.
import ftplib
import ssl
class ImplicitFTP_TLS(ftplib.FTP_TLS):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._sock = None
@property
def sock(self):
return self._sock
@sock.setter
def sock(self, value):
if value is not None and not isinstance(value, ssl.SSLSocket):
value = self.context.wrap_socket(value)
self._sock = value
def ntransfercmd(self, cmd, rest=None):
conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
if self._prot_p:
conn = self.context.wrap_socket(conn,
server_hostname=self.host,
session=self.sock.session)
return conn, size
Demo code
ftps = ImplicitFTP_TLS()
ftps.connect(host={your_ftp_host}, port=990, timeout=300)
ftps.login({your_ftp_account},{your_ftp_password})
ftps.prot_p()
# do something
print(ftps.getwelcome())
ftps.close()
Upvotes: 0
Reputation: 31
This is a reported bug in python: https://bugs.python.org/issue19500
You can apply the patch in a new class
class Explicit_FTP_TLS(ftplib.FTP_TLS):
"""Explicit FTPS, with shared TLS session"""
def ntransfercmd(self, cmd, rest=None):
conn, size = ftplib.FTP.ntransfercmd(self, cmd, rest)
if self._prot_p:
conn = self.context.wrap_socket(conn,
server_hostname=self.host,
session=self.sock.session)
return conn, size
Upvotes: 3