I think the issue lies in that you are trying to connect to an insecure FTP server using FTP over TLS. The code you provided has been tested with an insecure FTP server over port 21, and the same exact error is thrown. If that's the case, please try using instead the below. Please note, the below establishes an insecure connection between you and the FTP server.
import ftplib
hostname = '127.0.0.1'
username = 'admin'
password = ''
ftp = ftplib.FTP(hostname, username, password)
file = open('image.png','rb')
output_file_name = "image.png"
ftp.storbinary("STOR " + output_file_name, file)
file.close()
ftp.quit()
Update 1
This update shows how to reprocduce the error the questioner is referring to, i.e., "An existing connection was forcibly closed by...", as well as the following behaviour: "I can rename a file on the server using Python with this command: ftps.rename('a.txt', 'b.txt')
". The following steps are on a windows machine, but shouldn't be that different on other systems as well.
First, download and install FileZilla server on your machine. Start the server and go to the Administration Interface. From there, navigate to "Server" in the file menu and then click on "Configure...". Under "Users" make sure you have an "admin" user with blank password (for the purposes of this demo) and a folder (point) mounted serving as the FTP directory. Within that folder create a txt file named "a.txt" (doesn't need to have any contents). Make sure your server is up and running on port 21.
Now, for the FTP client, create a python file and paste the following code. Make sure you create a txt file named "hello.txt" in the same directory as the python file, with some text inside, e.g., "Hello World!". Next, run the python file (FTP cLient). You will notice that an error is thrown at line 9 ftps.storbinary("STOR " + output_file_name, open('hello.txt','rb'))
, saying "...An existing connection was forcibly closed by the remote host". Having a look now at the FTP directory of your server, you will see that the file named "a.txt" has been renamed to "b.txt", while there is also a file named "hello.txt", however, without any contents inside (i.e., empty file).
PS: If you are going to rerun the client, remember to rename the "b.txt" file in the FTP directory back to its original name ("a.txt"), otherwise an error will be thrown when attempting to rename it from the client.
import ftplib
ftps = ftplib.FTP_TLS()
ftps.connect("127.0.0.1", 21)
ftps.auth()
ftps.login("admin","")
ftps.prot_p()
ftps.rename('a.txt', 'b.txt')
output_file_name = "hello.txt"
ftps.storbinary("STOR " + output_file_name, open('hello.txt','rb'))
ftps.quit()
Update 2
Although the above explains how to reproduce the issue described by the original poster, it does not solve the issue in any way. As it turns out (and correctly pointed out by @Martin Prikryl), the latest version of FileZilla server has TLS enabled by default, meaning that with the above code sample, the client does connect to an FTP over TLS server. Thus, the issue remains and probably lies elsewhere. The answer will remain posted in case future readers benefit from it, or in case the author returns with new info on the issue.