I have a small code that uploads file to FTPS server (no, SFTP is not an option :( ). However after successful upload SSLError is raised.
from ftplib import FTP_TLS, parse227, parse229
import io
import os
import socket
import six
def ensure_binary(value):
if isinstance(value, six.text_type):
value = value.encode(encoding='utf-8')
return value
class FTP_TLS_Host(FTP_TLS):
"""FTP_TLS class that ignores host from FTP server."""
def makepasv(self):
"""Set passive command, but ignore host from ftp response."""
if self.af == socket.AF_INET:
__, port = parse227(self.sendcmd('PASV'))
host = self.host
else:
host, port = parse229(self.sendcmd('EPSV'), self.sock.getpeername())
return host, port
class FTPSClient(object):
def __init__(self, username, password, hostname, port=990):
self.username = username
self.password = password
self.hostname = hostname
self.port = port
def get_conn(self, ftp_class=FTP_TLS_Host):
conn = ftp_class(timeout=10)
conn.connect(self.hostname, self.port)
conn.login(self.username, self.password)
conn.prot_p()
return conn
def upload(self, content, filename_server):
ftps = self.get_conn()
binary = io.BytesIO(ensure_binary(content))
ftps.storbinary('STOR %s' % filename_server, binary)
ftps_client = FTPSClient(
username=os.environ['FTPS_USERNAME'],
password=os.environ['FTPS_PASSWORD'],
hostname=os.environ['FTPS_HOST'],
port=989,
)
ftps_client.upload('content', 'test.txt')
This is traceback:
File "/test.py", line 54, in <module>
ftps_client.upload('content', 'test.txt')
File "test.py", line 45, in upload
ftps.storbinary('STOR %s' % filename_server, binary)
File "/2.7/lib/python2.7/ftplib.py", line 769, in storbinary
conn.unwrap()
File "/2.7/lib/python2.7/ssl.py", line 823, in unwrap
s = self._sslobj.shutdown()
ssl.SSLError: ('The read operation timed out',)
How do I upload there without getting SSLError?